1 // Copyright (c) 2012 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/command_line.h" 6 #include "base/json/json_file_value_serializer.h" 7 #include "base/logging.h" 8 #include "base/path_service.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "chrome/common/chrome_paths.h" 11 #include "chrome/common/chrome_switches.h" 12 #include "chrome/common/extensions/extension_test_util.h" 13 #include "chrome/common/extensions/features/feature_channel.h" 14 #include "chrome/common/extensions/permissions/chrome_permission_message_provider.h" 15 #include "chrome/common/extensions/permissions/permission_message_util.h" 16 #include "chrome/common/extensions/permissions/socket_permission.h" 17 #include "extensions/common/error_utils.h" 18 #include "extensions/common/extension.h" 19 #include "extensions/common/permissions/permission_message_provider.h" 20 #include "extensions/common/permissions/permission_set.h" 21 #include "extensions/common/permissions/permissions_data.h" 22 #include "extensions/common/permissions/permissions_info.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 25 using extension_test_util::LoadManifest; 26 27 namespace extensions { 28 29 namespace { 30 31 static void AddPattern(URLPatternSet* extent, const std::string& pattern) { 32 int schemes = URLPattern::SCHEME_ALL; 33 extent->AddPattern(URLPattern(schemes, pattern)); 34 } 35 36 size_t IndexOf(const std::vector<base::string16>& warnings, 37 const std::string& warning) { 38 for (size_t i = 0; i < warnings.size(); ++i) { 39 if (warnings[i] == ASCIIToUTF16(warning)) 40 return i; 41 } 42 43 return warnings.size(); 44 } 45 46 bool Contains(const std::vector<base::string16>& warnings, 47 const std::string& warning) { 48 return IndexOf(warnings, warning) != warnings.size(); 49 } 50 51 } // namespace 52 53 // Tests GetByID. 54 TEST(PermissionsTest, GetByID) { 55 PermissionsInfo* info = PermissionsInfo::GetInstance(); 56 APIPermissionSet apis = info->GetAll(); 57 for (APIPermissionSet::const_iterator i = apis.begin(); 58 i != apis.end(); ++i) { 59 EXPECT_EQ(i->id(), i->info()->id()); 60 } 61 } 62 63 // Tests that GetByName works with normal permission names and aliases. 64 TEST(PermissionsTest, GetByName) { 65 PermissionsInfo* info = PermissionsInfo::GetInstance(); 66 EXPECT_EQ(APIPermission::kTab, info->GetByName("tabs")->id()); 67 EXPECT_EQ(APIPermission::kManagement, 68 info->GetByName("management")->id()); 69 EXPECT_FALSE(info->GetByName("alsdkfjasldkfj")); 70 } 71 72 TEST(PermissionsTest, GetAll) { 73 size_t count = 0; 74 PermissionsInfo* info = PermissionsInfo::GetInstance(); 75 APIPermissionSet apis = info->GetAll(); 76 for (APIPermissionSet::const_iterator api = apis.begin(); 77 api != apis.end(); ++api) { 78 // Make sure only the valid permission IDs get returned. 79 EXPECT_NE(APIPermission::kInvalid, api->id()); 80 EXPECT_NE(APIPermission::kUnknown, api->id()); 81 count++; 82 } 83 EXPECT_EQ(count, info->get_permission_count()); 84 } 85 86 TEST(PermissionsTest, GetAllByName) { 87 std::set<std::string> names; 88 names.insert("background"); 89 names.insert("management"); 90 91 // This is an alias of kTab 92 names.insert("windows"); 93 94 // This unknown name should get dropped. 95 names.insert("sdlkfjasdlkfj"); 96 97 APIPermissionSet expected; 98 expected.insert(APIPermission::kBackground); 99 expected.insert(APIPermission::kManagement); 100 expected.insert(APIPermission::kTab); 101 102 EXPECT_EQ(expected, 103 PermissionsInfo::GetInstance()->GetAllByName(names)); 104 } 105 106 // Tests that the aliases are properly mapped. 107 TEST(PermissionsTest, Aliases) { 108 PermissionsInfo* info = PermissionsInfo::GetInstance(); 109 // tabs: tabs, windows 110 std::string tabs_name = "tabs"; 111 EXPECT_EQ(tabs_name, info->GetByID(APIPermission::kTab)->name()); 112 EXPECT_EQ(APIPermission::kTab, info->GetByName("tabs")->id()); 113 EXPECT_EQ(APIPermission::kTab, info->GetByName("windows")->id()); 114 115 // unlimitedStorage: unlimitedStorage, unlimited_storage 116 std::string storage_name = "unlimitedStorage"; 117 EXPECT_EQ(storage_name, info->GetByID( 118 APIPermission::kUnlimitedStorage)->name()); 119 EXPECT_EQ(APIPermission::kUnlimitedStorage, 120 info->GetByName("unlimitedStorage")->id()); 121 EXPECT_EQ(APIPermission::kUnlimitedStorage, 122 info->GetByName("unlimited_storage")->id()); 123 } 124 125 TEST(PermissionsTest, EffectiveHostPermissions) { 126 scoped_refptr<Extension> extension; 127 scoped_refptr<const PermissionSet> permissions; 128 129 extension = LoadManifest("effective_host_permissions", "empty.json"); 130 permissions = extension->GetActivePermissions(); 131 EXPECT_EQ(0u, 132 PermissionsData::GetEffectiveHostPermissions(extension.get()) 133 .patterns().size()); 134 EXPECT_FALSE( 135 permissions->HasEffectiveAccessToURL(GURL("http://www.google.com"))); 136 EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts()); 137 138 extension = LoadManifest("effective_host_permissions", "one_host.json"); 139 permissions = extension->GetActivePermissions(); 140 EXPECT_TRUE(permissions->HasEffectiveAccessToURL( 141 GURL("http://www.google.com"))); 142 EXPECT_FALSE(permissions->HasEffectiveAccessToURL( 143 GURL("https://www.google.com"))); 144 EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts()); 145 146 extension = LoadManifest("effective_host_permissions", 147 "one_host_wildcard.json"); 148 permissions = extension->GetActivePermissions(); 149 EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com"))); 150 EXPECT_TRUE(permissions->HasEffectiveAccessToURL( 151 GURL("http://foo.google.com"))); 152 EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts()); 153 154 extension = LoadManifest("effective_host_permissions", "two_hosts.json"); 155 permissions = extension->GetActivePermissions(); 156 EXPECT_TRUE(permissions->HasEffectiveAccessToURL( 157 GURL("http://www.google.com"))); 158 EXPECT_TRUE(permissions->HasEffectiveAccessToURL( 159 GURL("http://www.reddit.com"))); 160 EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts()); 161 162 extension = LoadManifest("effective_host_permissions", 163 "https_not_considered.json"); 164 permissions = extension->GetActivePermissions(); 165 EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com"))); 166 EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("https://google.com"))); 167 EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts()); 168 169 extension = LoadManifest("effective_host_permissions", 170 "two_content_scripts.json"); 171 permissions = extension->GetActivePermissions(); 172 EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com"))); 173 EXPECT_TRUE(permissions->HasEffectiveAccessToURL( 174 GURL("http://www.reddit.com"))); 175 EXPECT_TRUE(permissions->HasEffectiveAccessToURL( 176 GURL("http://news.ycombinator.com"))); 177 EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts()); 178 179 extension = LoadManifest("effective_host_permissions", "all_hosts.json"); 180 permissions = extension->GetActivePermissions(); 181 EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://test/"))); 182 EXPECT_FALSE(permissions->HasEffectiveAccessToURL(GURL("https://test/"))); 183 EXPECT_TRUE( 184 permissions->HasEffectiveAccessToURL(GURL("http://www.google.com"))); 185 EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts()); 186 187 extension = LoadManifest("effective_host_permissions", "all_hosts2.json"); 188 permissions = extension->GetActivePermissions(); 189 EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://test/"))); 190 EXPECT_TRUE( 191 permissions->HasEffectiveAccessToURL(GURL("http://www.google.com"))); 192 EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts()); 193 194 extension = LoadManifest("effective_host_permissions", "all_hosts3.json"); 195 permissions = extension->GetActivePermissions(); 196 EXPECT_FALSE(permissions->HasEffectiveAccessToURL(GURL("http://test/"))); 197 EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("https://test/"))); 198 EXPECT_TRUE( 199 permissions->HasEffectiveAccessToURL(GURL("http://www.google.com"))); 200 EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts()); 201 } 202 203 TEST(PermissionsTest, ExplicitAccessToOrigin) { 204 APIPermissionSet apis; 205 ManifestPermissionSet manifest_permissions; 206 URLPatternSet explicit_hosts; 207 URLPatternSet scriptable_hosts; 208 209 AddPattern(&explicit_hosts, "http://*.google.com/*"); 210 // The explicit host paths should get set to /*. 211 AddPattern(&explicit_hosts, "http://www.example.com/a/particular/path/*"); 212 213 scoped_refptr<PermissionSet> perm_set = new PermissionSet( 214 apis, manifest_permissions, explicit_hosts, scriptable_hosts); 215 ASSERT_TRUE(perm_set->HasExplicitAccessToOrigin( 216 GURL("http://www.google.com/"))); 217 ASSERT_TRUE(perm_set->HasExplicitAccessToOrigin( 218 GURL("http://test.google.com/"))); 219 ASSERT_TRUE(perm_set->HasExplicitAccessToOrigin( 220 GURL("http://www.example.com"))); 221 ASSERT_TRUE(perm_set->HasEffectiveAccessToURL( 222 GURL("http://www.example.com"))); 223 ASSERT_FALSE(perm_set->HasExplicitAccessToOrigin( 224 GURL("http://test.example.com"))); 225 } 226 227 TEST(PermissionsTest, CreateUnion) { 228 APIPermission* permission = NULL; 229 230 ManifestPermissionSet manifest_permissions; 231 APIPermissionSet apis1; 232 APIPermissionSet apis2; 233 APIPermissionSet expected_apis; 234 235 URLPatternSet explicit_hosts1; 236 URLPatternSet explicit_hosts2; 237 URLPatternSet expected_explicit_hosts; 238 239 URLPatternSet scriptable_hosts1; 240 URLPatternSet scriptable_hosts2; 241 URLPatternSet expected_scriptable_hosts; 242 243 URLPatternSet effective_hosts; 244 245 scoped_refptr<PermissionSet> set1; 246 scoped_refptr<PermissionSet> set2; 247 scoped_refptr<PermissionSet> union_set; 248 249 const APIPermissionInfo* permission_info = 250 PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket); 251 permission = permission_info->CreateAPIPermission(); 252 { 253 scoped_ptr<base::ListValue> value(new base::ListValue()); 254 value->Append( 255 base::Value::CreateStringValue("tcp-connect:*.example.com:80")); 256 value->Append(base::Value::CreateStringValue("udp-bind::8080")); 257 value->Append(base::Value::CreateStringValue("udp-send-to::8888")); 258 if (!permission->FromValue(value.get())) { 259 NOTREACHED(); 260 } 261 } 262 263 // Union with an empty set. 264 apis1.insert(APIPermission::kTab); 265 apis1.insert(APIPermission::kBackground); 266 apis1.insert(permission->Clone()); 267 expected_apis.insert(APIPermission::kTab); 268 expected_apis.insert(APIPermission::kBackground); 269 expected_apis.insert(permission); 270 271 AddPattern(&explicit_hosts1, "http://*.google.com/*"); 272 AddPattern(&expected_explicit_hosts, "http://*.google.com/*"); 273 AddPattern(&effective_hosts, "http://*.google.com/*"); 274 275 set1 = new PermissionSet(apis1, manifest_permissions, 276 explicit_hosts1, scriptable_hosts1); 277 set2 = new PermissionSet(apis2, manifest_permissions, 278 explicit_hosts2, scriptable_hosts2); 279 union_set = PermissionSet::CreateUnion(set1.get(), set2.get()); 280 EXPECT_TRUE(set1->Contains(*set2.get())); 281 EXPECT_TRUE(set1->Contains(*union_set.get())); 282 EXPECT_FALSE(set2->Contains(*set1.get())); 283 EXPECT_FALSE(set2->Contains(*union_set.get())); 284 EXPECT_TRUE(union_set->Contains(*set1.get())); 285 EXPECT_TRUE(union_set->Contains(*set2.get())); 286 287 EXPECT_FALSE(union_set->HasEffectiveFullAccess()); 288 EXPECT_EQ(expected_apis, union_set->apis()); 289 EXPECT_EQ(expected_explicit_hosts, union_set->explicit_hosts()); 290 EXPECT_EQ(expected_scriptable_hosts, union_set->scriptable_hosts()); 291 EXPECT_EQ(expected_explicit_hosts, union_set->effective_hosts()); 292 293 // Now use a real second set. 294 apis2.insert(APIPermission::kTab); 295 apis2.insert(APIPermission::kProxy); 296 apis2.insert(APIPermission::kClipboardWrite); 297 apis2.insert(APIPermission::kPlugin); 298 299 permission = permission_info->CreateAPIPermission(); 300 { 301 scoped_ptr<base::ListValue> value(new base::ListValue()); 302 value->Append( 303 base::Value::CreateStringValue("tcp-connect:*.example.com:80")); 304 value->Append(base::Value::CreateStringValue("udp-send-to::8899")); 305 if (!permission->FromValue(value.get())) { 306 NOTREACHED(); 307 } 308 } 309 apis2.insert(permission); 310 311 expected_apis.insert(APIPermission::kTab); 312 expected_apis.insert(APIPermission::kProxy); 313 expected_apis.insert(APIPermission::kClipboardWrite); 314 expected_apis.insert(APIPermission::kPlugin); 315 316 permission = permission_info->CreateAPIPermission(); 317 { 318 scoped_ptr<base::ListValue> value(new base::ListValue()); 319 value->Append( 320 base::Value::CreateStringValue("tcp-connect:*.example.com:80")); 321 value->Append(base::Value::CreateStringValue("udp-bind::8080")); 322 value->Append(base::Value::CreateStringValue("udp-send-to::8888")); 323 value->Append(base::Value::CreateStringValue("udp-send-to::8899")); 324 if (!permission->FromValue(value.get())) { 325 NOTREACHED(); 326 } 327 } 328 // Insert a new permission socket permisssion which will replace the old one. 329 expected_apis.insert(permission); 330 331 AddPattern(&explicit_hosts2, "http://*.example.com/*"); 332 AddPattern(&scriptable_hosts2, "http://*.google.com/*"); 333 AddPattern(&expected_explicit_hosts, "http://*.example.com/*"); 334 AddPattern(&expected_scriptable_hosts, "http://*.google.com/*"); 335 336 URLPatternSet::CreateUnion( 337 explicit_hosts2, scriptable_hosts2, &effective_hosts); 338 339 set2 = new PermissionSet(apis2, manifest_permissions, 340 explicit_hosts2, scriptable_hosts2); 341 union_set = PermissionSet::CreateUnion(set1.get(), set2.get()); 342 343 EXPECT_FALSE(set1->Contains(*set2.get())); 344 EXPECT_FALSE(set1->Contains(*union_set.get())); 345 EXPECT_FALSE(set2->Contains(*set1.get())); 346 EXPECT_FALSE(set2->Contains(*union_set.get())); 347 EXPECT_TRUE(union_set->Contains(*set1.get())); 348 EXPECT_TRUE(union_set->Contains(*set2.get())); 349 350 EXPECT_TRUE(union_set->HasEffectiveFullAccess()); 351 EXPECT_TRUE(union_set->HasEffectiveAccessToAllHosts()); 352 EXPECT_EQ(expected_apis, union_set->apis()); 353 EXPECT_EQ(expected_explicit_hosts, union_set->explicit_hosts()); 354 EXPECT_EQ(expected_scriptable_hosts, union_set->scriptable_hosts()); 355 EXPECT_EQ(effective_hosts, union_set->effective_hosts()); 356 } 357 358 TEST(PermissionsTest, CreateIntersection) { 359 APIPermission* permission = NULL; 360 361 ManifestPermissionSet manifest_permissions; 362 APIPermissionSet apis1; 363 APIPermissionSet apis2; 364 APIPermissionSet expected_apis; 365 366 URLPatternSet explicit_hosts1; 367 URLPatternSet explicit_hosts2; 368 URLPatternSet expected_explicit_hosts; 369 370 URLPatternSet scriptable_hosts1; 371 URLPatternSet scriptable_hosts2; 372 URLPatternSet expected_scriptable_hosts; 373 374 URLPatternSet effective_hosts; 375 376 scoped_refptr<PermissionSet> set1; 377 scoped_refptr<PermissionSet> set2; 378 scoped_refptr<PermissionSet> new_set; 379 380 const APIPermissionInfo* permission_info = 381 PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket); 382 383 // Intersection with an empty set. 384 apis1.insert(APIPermission::kTab); 385 apis1.insert(APIPermission::kBackground); 386 permission = permission_info->CreateAPIPermission(); 387 { 388 scoped_ptr<base::ListValue> value(new base::ListValue()); 389 value->Append( 390 base::Value::CreateStringValue("tcp-connect:*.example.com:80")); 391 value->Append(base::Value::CreateStringValue("udp-bind::8080")); 392 value->Append(base::Value::CreateStringValue("udp-send-to::8888")); 393 if (!permission->FromValue(value.get())) { 394 NOTREACHED(); 395 } 396 } 397 apis1.insert(permission); 398 399 AddPattern(&explicit_hosts1, "http://*.google.com/*"); 400 AddPattern(&scriptable_hosts1, "http://www.reddit.com/*"); 401 402 set1 = new PermissionSet(apis1, manifest_permissions, 403 explicit_hosts1, scriptable_hosts1); 404 set2 = new PermissionSet(apis2, manifest_permissions, 405 explicit_hosts2, scriptable_hosts2); 406 new_set = PermissionSet::CreateIntersection(set1.get(), set2.get()); 407 EXPECT_TRUE(set1->Contains(*new_set.get())); 408 EXPECT_TRUE(set2->Contains(*new_set.get())); 409 EXPECT_TRUE(set1->Contains(*set2.get())); 410 EXPECT_FALSE(set2->Contains(*set1.get())); 411 EXPECT_FALSE(new_set->Contains(*set1.get())); 412 EXPECT_TRUE(new_set->Contains(*set2.get())); 413 414 EXPECT_TRUE(new_set->IsEmpty()); 415 EXPECT_FALSE(new_set->HasEffectiveFullAccess()); 416 EXPECT_EQ(expected_apis, new_set->apis()); 417 EXPECT_EQ(expected_explicit_hosts, new_set->explicit_hosts()); 418 EXPECT_EQ(expected_scriptable_hosts, new_set->scriptable_hosts()); 419 EXPECT_EQ(expected_explicit_hosts, new_set->effective_hosts()); 420 421 // Now use a real second set. 422 apis2.insert(APIPermission::kTab); 423 apis2.insert(APIPermission::kProxy); 424 apis2.insert(APIPermission::kClipboardWrite); 425 apis2.insert(APIPermission::kPlugin); 426 permission = permission_info->CreateAPIPermission(); 427 { 428 scoped_ptr<base::ListValue> value(new base::ListValue()); 429 value->Append(base::Value::CreateStringValue("udp-bind::8080")); 430 value->Append(base::Value::CreateStringValue("udp-send-to::8888")); 431 value->Append(base::Value::CreateStringValue("udp-send-to::8899")); 432 if (!permission->FromValue(value.get())) { 433 NOTREACHED(); 434 } 435 } 436 apis2.insert(permission); 437 438 expected_apis.insert(APIPermission::kTab); 439 permission = permission_info->CreateAPIPermission(); 440 { 441 scoped_ptr<base::ListValue> value(new base::ListValue()); 442 value->Append(base::Value::CreateStringValue("udp-bind::8080")); 443 value->Append(base::Value::CreateStringValue("udp-send-to::8888")); 444 if (!permission->FromValue(value.get())) { 445 NOTREACHED(); 446 } 447 } 448 expected_apis.insert(permission); 449 450 AddPattern(&explicit_hosts2, "http://*.example.com/*"); 451 AddPattern(&explicit_hosts2, "http://*.google.com/*"); 452 AddPattern(&scriptable_hosts2, "http://*.google.com/*"); 453 AddPattern(&expected_explicit_hosts, "http://*.google.com/*"); 454 455 effective_hosts.ClearPatterns(); 456 AddPattern(&effective_hosts, "http://*.google.com/*"); 457 458 set2 = new PermissionSet(apis2, manifest_permissions, 459 explicit_hosts2, scriptable_hosts2); 460 new_set = PermissionSet::CreateIntersection(set1.get(), set2.get()); 461 462 EXPECT_TRUE(set1->Contains(*new_set.get())); 463 EXPECT_TRUE(set2->Contains(*new_set.get())); 464 EXPECT_FALSE(set1->Contains(*set2.get())); 465 EXPECT_FALSE(set2->Contains(*set1.get())); 466 EXPECT_FALSE(new_set->Contains(*set1.get())); 467 EXPECT_FALSE(new_set->Contains(*set2.get())); 468 469 EXPECT_FALSE(new_set->HasEffectiveFullAccess()); 470 EXPECT_FALSE(new_set->HasEffectiveAccessToAllHosts()); 471 EXPECT_EQ(expected_apis, new_set->apis()); 472 EXPECT_EQ(expected_explicit_hosts, new_set->explicit_hosts()); 473 EXPECT_EQ(expected_scriptable_hosts, new_set->scriptable_hosts()); 474 EXPECT_EQ(effective_hosts, new_set->effective_hosts()); 475 } 476 477 TEST(PermissionsTest, CreateDifference) { 478 APIPermission* permission = NULL; 479 480 ManifestPermissionSet manifest_permissions; 481 APIPermissionSet apis1; 482 APIPermissionSet apis2; 483 APIPermissionSet expected_apis; 484 485 URLPatternSet explicit_hosts1; 486 URLPatternSet explicit_hosts2; 487 URLPatternSet expected_explicit_hosts; 488 489 URLPatternSet scriptable_hosts1; 490 URLPatternSet scriptable_hosts2; 491 URLPatternSet expected_scriptable_hosts; 492 493 URLPatternSet effective_hosts; 494 495 scoped_refptr<PermissionSet> set1; 496 scoped_refptr<PermissionSet> set2; 497 scoped_refptr<PermissionSet> new_set; 498 499 const APIPermissionInfo* permission_info = 500 PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket); 501 502 // Difference with an empty set. 503 apis1.insert(APIPermission::kTab); 504 apis1.insert(APIPermission::kBackground); 505 permission = permission_info->CreateAPIPermission(); 506 { 507 scoped_ptr<base::ListValue> value(new base::ListValue()); 508 value->Append( 509 base::Value::CreateStringValue("tcp-connect:*.example.com:80")); 510 value->Append(base::Value::CreateStringValue("udp-bind::8080")); 511 value->Append(base::Value::CreateStringValue("udp-send-to::8888")); 512 if (!permission->FromValue(value.get())) { 513 NOTREACHED(); 514 } 515 } 516 apis1.insert(permission); 517 518 AddPattern(&explicit_hosts1, "http://*.google.com/*"); 519 AddPattern(&scriptable_hosts1, "http://www.reddit.com/*"); 520 521 set1 = new PermissionSet(apis1, manifest_permissions, 522 explicit_hosts1, scriptable_hosts1); 523 set2 = new PermissionSet(apis2, manifest_permissions, 524 explicit_hosts2, scriptable_hosts2); 525 new_set = PermissionSet::CreateDifference(set1.get(), set2.get()); 526 EXPECT_EQ(*set1.get(), *new_set.get()); 527 528 // Now use a real second set. 529 apis2.insert(APIPermission::kTab); 530 apis2.insert(APIPermission::kProxy); 531 apis2.insert(APIPermission::kClipboardWrite); 532 apis2.insert(APIPermission::kPlugin); 533 permission = permission_info->CreateAPIPermission(); 534 { 535 scoped_ptr<base::ListValue> value(new base::ListValue()); 536 value->Append( 537 base::Value::CreateStringValue("tcp-connect:*.example.com:80")); 538 value->Append(base::Value::CreateStringValue("udp-send-to::8899")); 539 if (!permission->FromValue(value.get())) { 540 NOTREACHED(); 541 } 542 } 543 apis2.insert(permission); 544 545 expected_apis.insert(APIPermission::kBackground); 546 permission = permission_info->CreateAPIPermission(); 547 { 548 scoped_ptr<base::ListValue> value(new base::ListValue()); 549 value->Append(base::Value::CreateStringValue("udp-bind::8080")); 550 value->Append(base::Value::CreateStringValue("udp-send-to::8888")); 551 if (!permission->FromValue(value.get())) { 552 NOTREACHED(); 553 } 554 } 555 expected_apis.insert(permission); 556 557 AddPattern(&explicit_hosts2, "http://*.example.com/*"); 558 AddPattern(&explicit_hosts2, "http://*.google.com/*"); 559 AddPattern(&scriptable_hosts2, "http://*.google.com/*"); 560 AddPattern(&expected_scriptable_hosts, "http://www.reddit.com/*"); 561 562 effective_hosts.ClearPatterns(); 563 AddPattern(&effective_hosts, "http://www.reddit.com/*"); 564 565 set2 = new PermissionSet(apis2, manifest_permissions, 566 explicit_hosts2, scriptable_hosts2); 567 new_set = PermissionSet::CreateDifference(set1.get(), set2.get()); 568 569 EXPECT_TRUE(set1->Contains(*new_set.get())); 570 EXPECT_FALSE(set2->Contains(*new_set.get())); 571 572 EXPECT_FALSE(new_set->HasEffectiveFullAccess()); 573 EXPECT_FALSE(new_set->HasEffectiveAccessToAllHosts()); 574 EXPECT_EQ(expected_apis, new_set->apis()); 575 EXPECT_EQ(expected_explicit_hosts, new_set->explicit_hosts()); 576 EXPECT_EQ(expected_scriptable_hosts, new_set->scriptable_hosts()); 577 EXPECT_EQ(effective_hosts, new_set->effective_hosts()); 578 579 // |set3| = |set1| - |set2| --> |set3| intersect |set2| == empty_set 580 set1 = PermissionSet::CreateIntersection(new_set.get(), set2.get()); 581 EXPECT_TRUE(set1->IsEmpty()); 582 } 583 584 TEST(PermissionsTest, IsPrivilegeIncrease) { 585 const struct { 586 const char* base_name; 587 bool expect_increase; 588 } kTests[] = { 589 { "allhosts1", false }, // all -> all 590 { "allhosts2", false }, // all -> one 591 { "allhosts3", true }, // one -> all 592 { "hosts1", false }, // http://a,http://b -> http://a,http://b 593 { "hosts2", true }, // http://a,http://b -> https://a,http://*.b 594 { "hosts3", false }, // http://a,http://b -> http://a 595 { "hosts4", true }, // http://a -> http://a,http://b 596 { "hosts5", false }, // http://a,b,c -> http://a,b,c + https://a,b,c 597 { "hosts6", false }, // http://a.com -> http://a.com + http://a.co.uk 598 { "permissions1", false }, // tabs -> tabs 599 { "permissions2", true }, // tabs -> tabs,bookmarks 600 { "permissions3", true }, // http://a -> http://a,tabs 601 { "permissions5", true }, // bookmarks -> bookmarks,history 602 { "equivalent_warnings", false }, // tabs --> tabs, webNavigation 603 #if !defined(OS_CHROMEOS) // plugins aren't allowed in ChromeOS 604 { "permissions4", false }, // plugin -> plugin,tabs 605 { "plugin1", false }, // plugin -> plugin 606 { "plugin2", false }, // plugin -> none 607 { "plugin3", true }, // none -> plugin 608 #endif 609 { "storage", false }, // none -> storage 610 { "notifications", false }, // none -> notifications 611 { "platformapp1", false }, // host permissions for platform apps 612 { "platformapp2", true }, // API permissions for platform apps 613 { "media_galleries1", true }, // all -> read|all 614 { "media_galleries2", true }, // read|all -> read|delete|copyTo|all 615 { "media_galleries3", true }, // all -> read|delete|all 616 { "media_galleries4", false }, // read|all -> all 617 { "media_galleries5", false }, // read|copyTo|delete|all -> read|all 618 { "media_galleries6", false }, // read|all -> read|all 619 { "media_galleries7", true }, // read|delete|all -> read|copyTo|delete|all 620 { "sockets1", true }, // none -> tcp:*:* 621 { "sockets2", false }, // tcp:*:* -> tcp:*:* 622 { "sockets3", true }, // tcp:a.com:80 -> tcp:*:* 623 }; 624 625 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) { 626 scoped_refptr<Extension> old_extension( 627 LoadManifest("allow_silent_upgrade", 628 std::string(kTests[i].base_name) + "_old.json")); 629 scoped_refptr<Extension> new_extension( 630 LoadManifest("allow_silent_upgrade", 631 std::string(kTests[i].base_name) + "_new.json")); 632 633 EXPECT_TRUE(new_extension.get()) << kTests[i].base_name << "_new.json"; 634 if (!new_extension.get()) 635 continue; 636 637 scoped_refptr<const PermissionSet> old_p( 638 old_extension->GetActivePermissions()); 639 scoped_refptr<const PermissionSet> new_p( 640 new_extension->GetActivePermissions()); 641 Manifest::Type extension_type = old_extension->GetType(); 642 643 bool increased = PermissionMessageProvider::Get()->IsPrivilegeIncrease( 644 old_p.get(), new_p.get(), extension_type); 645 EXPECT_EQ(kTests[i].expect_increase, increased) << kTests[i].base_name; 646 } 647 } 648 649 TEST(PermissionsTest, PermissionMessages) { 650 // Ensure that all permissions that needs to show install UI actually have 651 // strings associated with them. 652 APIPermissionSet skip; 653 654 // These are considered "nuisance" or "trivial" permissions that don't need 655 // a prompt. 656 skip.insert(APIPermission::kActiveTab); 657 skip.insert(APIPermission::kAdView); 658 skip.insert(APIPermission::kAlarms); 659 skip.insert(APIPermission::kAlwaysOnTopWindows); 660 skip.insert(APIPermission::kAppCurrentWindowInternal); 661 skip.insert(APIPermission::kAppRuntime); 662 skip.insert(APIPermission::kAppWindow); 663 skip.insert(APIPermission::kAudio); 664 skip.insert(APIPermission::kBrowsingData); 665 skip.insert(APIPermission::kCastStreaming); 666 skip.insert(APIPermission::kContextMenus); 667 skip.insert(APIPermission::kDiagnostics); 668 skip.insert(APIPermission::kDns); 669 skip.insert(APIPermission::kDownloadsShelf); 670 skip.insert(APIPermission::kFontSettings); 671 skip.insert(APIPermission::kFullscreen); 672 skip.insert(APIPermission::kGcm); 673 skip.insert(APIPermission::kIdle); 674 skip.insert(APIPermission::kIdltest); 675 skip.insert(APIPermission::kLogPrivate); 676 skip.insert(APIPermission::kNotification); 677 skip.insert(APIPermission::kPointerLock); 678 skip.insert(APIPermission::kPower); 679 skip.insert(APIPermission::kPushMessaging); 680 skip.insert(APIPermission::kSessions); 681 skip.insert(APIPermission::kStorage); 682 skip.insert(APIPermission::kSystemCpu); 683 skip.insert(APIPermission::kSystemDisplay); 684 skip.insert(APIPermission::kSystemMemory); 685 skip.insert(APIPermission::kSystemNetwork); 686 skip.insert(APIPermission::kSystemStorage); 687 skip.insert(APIPermission::kTts); 688 skip.insert(APIPermission::kUnlimitedStorage); 689 skip.insert(APIPermission::kWebView); 690 skip.insert(APIPermission::kOverrideEscFullscreen); 691 692 // TODO(erikkay) add a string for this permission. 693 skip.insert(APIPermission::kBackground); 694 695 skip.insert(APIPermission::kClipboardWrite); 696 697 // The cookie permission does nothing unless you have associated host 698 // permissions. 699 skip.insert(APIPermission::kCookie); 700 701 // These are warned as part of host permission checks. 702 skip.insert(APIPermission::kDeclarativeContent); 703 skip.insert(APIPermission::kPageCapture); 704 skip.insert(APIPermission::kProxy); 705 skip.insert(APIPermission::kTabCapture); 706 skip.insert(APIPermission::kWebRequest); 707 skip.insert(APIPermission::kWebRequestBlocking); 708 709 // This permission requires explicit user action (context menu handler) 710 // so we won't prompt for it for now. 711 skip.insert(APIPermission::kFileBrowserHandler); 712 713 // These permissions require explicit user action (configuration dialog) 714 // so we don't prompt for them at install time. 715 skip.insert(APIPermission::kMediaGalleries); 716 717 // If you've turned on the experimental command-line flag, we don't need 718 // to warn you further. 719 skip.insert(APIPermission::kExperimental); 720 721 // The Identity API has its own server-driven permission prompts. 722 skip.insert(APIPermission::kIdentity); 723 724 // These are private. 725 skip.insert(APIPermission::kAutoTestPrivate); 726 skip.insert(APIPermission::kBookmarkManagerPrivate); 727 skip.insert(APIPermission::kBrailleDisplayPrivate); 728 skip.insert(APIPermission::kCast); 729 skip.insert(APIPermission::kCastStreaming); 730 skip.insert(APIPermission::kChromeosInfoPrivate); 731 skip.insert(APIPermission::kCloudPrintPrivate); 732 skip.insert(APIPermission::kCommandLinePrivate); 733 skip.insert(APIPermission::kDeveloperPrivate); 734 skip.insert(APIPermission::kDial); 735 skip.insert(APIPermission::kDownloadsInternal); 736 skip.insert(APIPermission::kEchoPrivate); 737 skip.insert(APIPermission::kEnterprisePlatformKeysPrivate); 738 skip.insert(APIPermission::kFeedbackPrivate); 739 skip.insert(APIPermission::kFileBrowserHandlerInternal); 740 skip.insert(APIPermission::kFileBrowserPrivate); 741 skip.insert(APIPermission::kFirstRunPrivate); 742 skip.insert(APIPermission::kIdentityPrivate); 743 skip.insert(APIPermission::kInfobars); 744 skip.insert(APIPermission::kInputMethodPrivate); 745 skip.insert(APIPermission::kMediaGalleriesPrivate); 746 skip.insert(APIPermission::kMediaPlayerPrivate); 747 skip.insert(APIPermission::kMetricsPrivate); 748 skip.insert(APIPermission::kMDns); 749 skip.insert(APIPermission::kPreferencesPrivate); 750 skip.insert(APIPermission::kPrincipalsPrivate); 751 skip.insert(APIPermission::kImageWriterPrivate); 752 skip.insert(APIPermission::kRtcPrivate); 753 skip.insert(APIPermission::kStreamsPrivate); 754 skip.insert(APIPermission::kSystemPrivate); 755 skip.insert(APIPermission::kTabCaptureForTab); 756 skip.insert(APIPermission::kTerminalPrivate); 757 skip.insert(APIPermission::kVirtualKeyboardPrivate); 758 skip.insert(APIPermission::kWallpaperPrivate); 759 skip.insert(APIPermission::kWebRequestInternal); 760 skip.insert(APIPermission::kWebrtcAudioPrivate); 761 skip.insert(APIPermission::kWebrtcLoggingPrivate); 762 skip.insert(APIPermission::kWebstorePrivate); 763 764 // Warned as part of host permissions. 765 skip.insert(APIPermission::kDevtools); 766 767 // Platform apps. 768 skip.insert(APIPermission::kBluetooth); 769 skip.insert(APIPermission::kFileSystem); 770 skip.insert(APIPermission::kFileSystemProvider); 771 skip.insert(APIPermission::kFileSystemRetainEntries); 772 skip.insert(APIPermission::kSocket); 773 skip.insert(APIPermission::kUsbDevice); 774 775 PermissionsInfo* info = PermissionsInfo::GetInstance(); 776 APIPermissionSet permissions = info->GetAll(); 777 for (APIPermissionSet::const_iterator i = permissions.begin(); 778 i != permissions.end(); ++i) { 779 const APIPermissionInfo* permission_info = i->info(); 780 EXPECT_TRUE(permission_info != NULL); 781 782 if (skip.count(i->id())) { 783 EXPECT_EQ(PermissionMessage::kNone, permission_info->message_id()) 784 << "unexpected message_id for " << permission_info->name(); 785 } else { 786 EXPECT_NE(PermissionMessage::kNone, permission_info->message_id()) 787 << "missing message_id for " << permission_info->name(); 788 } 789 } 790 } 791 792 TEST(PermissionsTest, FileSystemPermissionMessages) { 793 APIPermissionSet api_permissions; 794 api_permissions.insert(APIPermission::kFileSystemWrite); 795 api_permissions.insert(APIPermission::kFileSystemDirectory); 796 scoped_refptr<PermissionSet> permissions( 797 new PermissionSet(api_permissions, ManifestPermissionSet(), 798 URLPatternSet(), URLPatternSet())); 799 PermissionMessages messages = 800 PermissionMessageProvider::Get()->GetPermissionMessages( 801 permissions, Manifest::TYPE_PLATFORM_APP); 802 ASSERT_EQ(2u, messages.size()); 803 std::sort(messages.begin(), messages.end()); 804 std::set<PermissionMessage::ID> ids; 805 for (PermissionMessages::const_iterator it = messages.begin(); 806 it != messages.end(); ++it) { 807 ids.insert(it->id()); 808 } 809 EXPECT_TRUE(ContainsKey(ids, PermissionMessage::kFileSystemDirectory)); 810 EXPECT_TRUE(ContainsKey(ids, PermissionMessage::kFileSystemWrite)); 811 } 812 813 TEST(PermissionsTest, HiddenFileSystemPermissionMessages) { 814 APIPermissionSet api_permissions; 815 api_permissions.insert(APIPermission::kFileSystemWrite); 816 api_permissions.insert(APIPermission::kFileSystemDirectory); 817 api_permissions.insert(APIPermission::kFileSystemWriteDirectory); 818 scoped_refptr<PermissionSet> permissions( 819 new PermissionSet(api_permissions, ManifestPermissionSet(), 820 URLPatternSet(), URLPatternSet())); 821 PermissionMessages messages = 822 PermissionMessageProvider::Get()->GetPermissionMessages( 823 permissions, Manifest::TYPE_PLATFORM_APP); 824 ASSERT_EQ(1u, messages.size()); 825 EXPECT_EQ(PermissionMessage::kFileSystemWriteDirectory, messages[0].id()); 826 } 827 828 TEST(PermissionsTest, MergedFileSystemPermissionComparison) { 829 APIPermissionSet write_api_permissions; 830 write_api_permissions.insert(APIPermission::kFileSystemWrite); 831 scoped_refptr<PermissionSet> write_permissions( 832 new PermissionSet(write_api_permissions, ManifestPermissionSet(), 833 URLPatternSet(), URLPatternSet())); 834 835 APIPermissionSet directory_api_permissions; 836 directory_api_permissions.insert(APIPermission::kFileSystemDirectory); 837 scoped_refptr<PermissionSet> directory_permissions( 838 new PermissionSet(directory_api_permissions, ManifestPermissionSet(), 839 URLPatternSet(), URLPatternSet())); 840 841 APIPermissionSet write_directory_api_permissions; 842 write_directory_api_permissions.insert( 843 APIPermission::kFileSystemWriteDirectory); 844 scoped_refptr<PermissionSet> write_directory_permissions( 845 new PermissionSet(write_directory_api_permissions, 846 ManifestPermissionSet(), 847 URLPatternSet(), 848 URLPatternSet())); 849 850 const PermissionMessageProvider* provider = PermissionMessageProvider::Get(); 851 EXPECT_FALSE(provider->IsPrivilegeIncrease(write_directory_permissions, 852 write_permissions, 853 Manifest::TYPE_PLATFORM_APP)); 854 EXPECT_FALSE(provider->IsPrivilegeIncrease(write_directory_permissions, 855 directory_permissions, 856 Manifest::TYPE_PLATFORM_APP)); 857 EXPECT_TRUE(provider->IsPrivilegeIncrease(write_permissions, 858 directory_permissions, 859 Manifest::TYPE_PLATFORM_APP)); 860 EXPECT_TRUE(provider->IsPrivilegeIncrease(write_permissions, 861 write_directory_permissions, 862 Manifest::TYPE_PLATFORM_APP)); 863 EXPECT_TRUE(provider->IsPrivilegeIncrease(directory_permissions, 864 write_permissions, 865 Manifest::TYPE_PLATFORM_APP)); 866 EXPECT_TRUE(provider->IsPrivilegeIncrease(directory_permissions, 867 write_directory_permissions, 868 Manifest::TYPE_PLATFORM_APP)); 869 } 870 871 TEST(PermissionsTest, GetWarningMessages_ManyHosts) { 872 scoped_refptr<Extension> extension; 873 874 extension = LoadManifest("permissions", "many-hosts.json"); 875 std::vector<base::string16> warnings = 876 PermissionsData::GetPermissionMessageStrings(extension.get()); 877 ASSERT_EQ(1u, warnings.size()); 878 EXPECT_EQ("Access your data on encrypted.google.com and www.google.com", 879 UTF16ToUTF8(warnings[0])); 880 } 881 882 TEST(PermissionsTest, GetWarningMessages_Plugins) { 883 scoped_refptr<Extension> extension; 884 scoped_refptr<PermissionSet> permissions; 885 886 extension = LoadManifest("permissions", "plugins.json"); 887 std::vector<base::string16> warnings = 888 PermissionsData::GetPermissionMessageStrings(extension.get()); 889 // We don't parse the plugins key on Chrome OS, so it should not ask for any 890 // permissions. 891 #if defined(OS_CHROMEOS) 892 ASSERT_EQ(0u, warnings.size()); 893 #else 894 ASSERT_EQ(1u, warnings.size()); 895 EXPECT_EQ("Access all data on your computer and the websites you visit", 896 UTF16ToUTF8(warnings[0])); 897 #endif 898 } 899 900 TEST(PermissionsTest, GetWarningMessages_AudioVideo) { 901 // Both audio and video present. 902 scoped_refptr<Extension> extension = 903 LoadManifest("permissions", "audio-video.json"); 904 const PermissionMessageProvider* provider = PermissionMessageProvider::Get(); 905 PermissionSet* set = 906 const_cast<PermissionSet*>( 907 extension->GetActivePermissions().get()); 908 std::vector<base::string16> warnings = 909 provider->GetWarningMessages(set, extension->GetType()); 910 EXPECT_FALSE(Contains(warnings, "Use your microphone")); 911 EXPECT_FALSE(Contains(warnings, "Use your camera")); 912 EXPECT_TRUE(Contains(warnings, "Use your microphone and camera")); 913 size_t combined_index = IndexOf(warnings, "Use your microphone and camera"); 914 size_t combined_size = warnings.size(); 915 916 // Just audio present. 917 set->apis_.erase(APIPermission::kVideoCapture); 918 warnings = provider->GetWarningMessages(set, extension->GetType()); 919 EXPECT_EQ(combined_size, warnings.size()); 920 EXPECT_EQ(combined_index, IndexOf(warnings, "Use your microphone")); 921 EXPECT_FALSE(Contains(warnings, "Use your camera")); 922 EXPECT_FALSE(Contains(warnings, "Use your microphone and camera")); 923 924 // Just video present. 925 set->apis_.erase(APIPermission::kAudioCapture); 926 set->apis_.insert(APIPermission::kVideoCapture); 927 warnings = provider->GetWarningMessages(set, extension->GetType()); 928 EXPECT_EQ(combined_size, warnings.size()); 929 EXPECT_FALSE(Contains(warnings, "Use your microphone")); 930 EXPECT_FALSE(Contains(warnings, "Use your microphone and camera")); 931 EXPECT_TRUE(Contains(warnings, "Use your camera")); 932 } 933 934 TEST(PermissionsTest, GetWarningMessages_DeclarativeWebRequest) { 935 // Test that if the declarativeWebRequest permission is present 936 // in combination with all hosts permission, then only the warning 937 // for host permissions is shown, because that covers the use of 938 // declarativeWebRequest. 939 940 // Until Declarative Web Request is in stable, let's make sure it is enabled 941 // on the current channel. 942 ScopedCurrentChannel sc(chrome::VersionInfo::CHANNEL_CANARY); 943 944 // First verify that declarativeWebRequest produces a message when host 945 // permissions do not cover all hosts. 946 scoped_refptr<Extension> extension = 947 LoadManifest("permissions", "web_request_com_host_permissions.json"); 948 const PermissionMessageProvider* provider = PermissionMessageProvider::Get(); 949 const PermissionSet* set = extension->GetActivePermissions().get(); 950 std::vector<base::string16> warnings = 951 provider->GetWarningMessages(set, extension->GetType()); 952 EXPECT_TRUE(Contains(warnings, "Block parts of web pages")); 953 EXPECT_FALSE(Contains(warnings, "Access your data on all websites")); 954 955 // Now verify that declarativeWebRequest does not produce a message when host 956 // permissions do cover all hosts. 957 extension = 958 LoadManifest("permissions", "web_request_all_host_permissions.json"); 959 set = extension->GetActivePermissions().get(); 960 warnings = provider->GetWarningMessages(set, extension->GetType()); 961 EXPECT_FALSE(Contains(warnings, "Block parts of web pages")); 962 EXPECT_TRUE(Contains(warnings, "Access your data on all websites")); 963 } 964 965 TEST(PermissionsTest, GetWarningMessages_Serial) { 966 scoped_refptr<Extension> extension = 967 LoadManifest("permissions", "serial.json"); 968 969 EXPECT_TRUE(extension->is_platform_app()); 970 EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSerial)); 971 std::vector<base::string16> warnings = 972 PermissionsData::GetPermissionMessageStrings(extension.get()); 973 EXPECT_TRUE( 974 Contains(warnings, "Use serial devices attached to your computer")); 975 ASSERT_EQ(1u, warnings.size()); 976 } 977 978 TEST(PermissionsTest, GetWarningMessages_Socket_AnyHost) { 979 ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV); 980 981 scoped_refptr<Extension> extension = 982 LoadManifest("permissions", "socket_any_host.json"); 983 EXPECT_TRUE(extension->is_platform_app()); 984 EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSocket)); 985 std::vector<base::string16> warnings = 986 PermissionsData::GetPermissionMessageStrings(extension.get()); 987 EXPECT_EQ(1u, warnings.size()); 988 EXPECT_TRUE(Contains(warnings, "Exchange data with any computer " 989 "on the local network or internet")); 990 } 991 992 TEST(PermissionsTest, GetWarningMessages_Socket_OneDomainTwoHostnames) { 993 ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV); 994 995 scoped_refptr<Extension> extension = 996 LoadManifest("permissions", "socket_one_domain_two_hostnames.json"); 997 EXPECT_TRUE(extension->is_platform_app()); 998 EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSocket)); 999 std::vector<base::string16> warnings = 1000 PermissionsData::GetPermissionMessageStrings(extension.get()); 1001 1002 // Verify the warnings, including support for unicode characters, the fact 1003 // that domain host warnings come before specific host warnings, and the fact 1004 // that domains and hostnames are in alphabetical order regardless of the 1005 // order in the manifest file. 1006 EXPECT_EQ(2u, warnings.size()); 1007 if (warnings.size() > 0) 1008 EXPECT_EQ(warnings[0], 1009 UTF8ToUTF16("Exchange data with any computer in the domain " 1010 "example.org")); 1011 if (warnings.size() > 1) 1012 EXPECT_EQ(warnings[1], 1013 UTF8ToUTF16("Exchange data with the computers named: " 1014 "b\xC3\xA5r.example.com foo.example.com")); 1015 // "\xC3\xA5" = UTF-8 for lowercase A with ring above 1016 } 1017 1018 TEST(PermissionsTest, GetWarningMessages_Socket_TwoDomainsOneHostname) { 1019 ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV); 1020 1021 scoped_refptr<Extension> extension = 1022 LoadManifest("permissions", "socket_two_domains_one_hostname.json"); 1023 EXPECT_TRUE(extension->is_platform_app()); 1024 EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSocket)); 1025 std::vector<base::string16> warnings = 1026 PermissionsData::GetPermissionMessageStrings(extension.get()); 1027 1028 // Verify the warnings, including the fact that domain host warnings come 1029 // before specific host warnings and the fact that domains and hostnames are 1030 // in alphabetical order regardless of the order in the manifest file. 1031 EXPECT_EQ(2u, warnings.size()); 1032 if (warnings.size() > 0) 1033 EXPECT_EQ(warnings[0], 1034 UTF8ToUTF16("Exchange data with any computer in the domains: " 1035 "example.com foo.example.org")); 1036 if (warnings.size() > 1) 1037 EXPECT_EQ(warnings[1], 1038 UTF8ToUTF16("Exchange data with the computer named " 1039 "bar.example.org")); 1040 } 1041 1042 TEST(PermissionsTest, GetWarningMessages_PlatformApppHosts) { 1043 scoped_refptr<Extension> extension; 1044 1045 extension = LoadManifest("permissions", "platform_app_hosts.json"); 1046 EXPECT_TRUE(extension->is_platform_app()); 1047 std::vector<base::string16> warnings = 1048 PermissionsData::GetPermissionMessageStrings(extension.get()); 1049 ASSERT_EQ(0u, warnings.size()); 1050 1051 extension = LoadManifest("permissions", "platform_app_all_urls.json"); 1052 EXPECT_TRUE(extension->is_platform_app()); 1053 warnings = PermissionsData::GetPermissionMessageStrings(extension.get()); 1054 ASSERT_EQ(0u, warnings.size()); 1055 } 1056 1057 TEST(PermissionsTest, GetDistinctHosts) { 1058 URLPatternSet explicit_hosts; 1059 std::set<std::string> expected; 1060 expected.insert("www.foo.com"); 1061 expected.insert("www.bar.com"); 1062 expected.insert("www.baz.com"); 1063 1064 { 1065 SCOPED_TRACE("no dupes"); 1066 1067 // Simple list with no dupes. 1068 explicit_hosts.AddPattern( 1069 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path")); 1070 explicit_hosts.AddPattern( 1071 URLPattern(URLPattern::SCHEME_HTTP, "http://www.bar.com/path")); 1072 explicit_hosts.AddPattern( 1073 URLPattern(URLPattern::SCHEME_HTTP, "http://www.baz.com/path")); 1074 EXPECT_EQ(expected, 1075 permission_message_util::GetDistinctHosts( 1076 explicit_hosts, true, true)); 1077 } 1078 1079 { 1080 SCOPED_TRACE("two dupes"); 1081 1082 // Add some dupes. 1083 explicit_hosts.AddPattern( 1084 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path")); 1085 explicit_hosts.AddPattern( 1086 URLPattern(URLPattern::SCHEME_HTTP, "http://www.baz.com/path")); 1087 EXPECT_EQ(expected, 1088 permission_message_util::GetDistinctHosts( 1089 explicit_hosts, true, true)); 1090 } 1091 1092 { 1093 SCOPED_TRACE("schemes differ"); 1094 1095 // Add a pattern that differs only by scheme. This should be filtered out. 1096 explicit_hosts.AddPattern( 1097 URLPattern(URLPattern::SCHEME_HTTPS, "https://www.bar.com/path")); 1098 EXPECT_EQ(expected, 1099 permission_message_util::GetDistinctHosts( 1100 explicit_hosts, true, true)); 1101 } 1102 1103 { 1104 SCOPED_TRACE("paths differ"); 1105 1106 // Add some dupes by path. 1107 explicit_hosts.AddPattern( 1108 URLPattern(URLPattern::SCHEME_HTTP, "http://www.bar.com/pathypath")); 1109 EXPECT_EQ(expected, 1110 permission_message_util::GetDistinctHosts( 1111 explicit_hosts, true, true)); 1112 } 1113 1114 { 1115 SCOPED_TRACE("subdomains differ"); 1116 1117 // We don't do anything special for subdomains. 1118 explicit_hosts.AddPattern( 1119 URLPattern(URLPattern::SCHEME_HTTP, "http://monkey.www.bar.com/path")); 1120 explicit_hosts.AddPattern( 1121 URLPattern(URLPattern::SCHEME_HTTP, "http://bar.com/path")); 1122 1123 expected.insert("monkey.www.bar.com"); 1124 expected.insert("bar.com"); 1125 1126 EXPECT_EQ(expected, 1127 permission_message_util::GetDistinctHosts( 1128 explicit_hosts, true, true)); 1129 } 1130 1131 { 1132 SCOPED_TRACE("RCDs differ"); 1133 1134 // Now test for RCD uniquing. 1135 explicit_hosts.AddPattern( 1136 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path")); 1137 explicit_hosts.AddPattern( 1138 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path")); 1139 explicit_hosts.AddPattern( 1140 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.de/path")); 1141 explicit_hosts.AddPattern( 1142 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca.us/path")); 1143 explicit_hosts.AddPattern( 1144 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.net/path")); 1145 explicit_hosts.AddPattern( 1146 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com.my/path")); 1147 1148 // This is an unknown RCD, which shouldn't be uniqued out. 1149 explicit_hosts.AddPattern( 1150 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.xyzzy/path")); 1151 // But it should only occur once. 1152 explicit_hosts.AddPattern( 1153 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.xyzzy/path")); 1154 1155 expected.insert("www.foo.xyzzy"); 1156 1157 EXPECT_EQ(expected, 1158 permission_message_util::GetDistinctHosts( 1159 explicit_hosts, true, true)); 1160 } 1161 1162 { 1163 SCOPED_TRACE("wildcards"); 1164 1165 explicit_hosts.AddPattern( 1166 URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com/*")); 1167 1168 expected.insert("*.google.com"); 1169 1170 EXPECT_EQ(expected, 1171 permission_message_util::GetDistinctHosts( 1172 explicit_hosts, true, true)); 1173 } 1174 1175 { 1176 SCOPED_TRACE("scriptable hosts"); 1177 1178 APIPermissionSet empty_perms; 1179 explicit_hosts.ClearPatterns(); 1180 URLPatternSet scriptable_hosts; 1181 expected.clear(); 1182 1183 explicit_hosts.AddPattern( 1184 URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com/*")); 1185 scriptable_hosts.AddPattern( 1186 URLPattern(URLPattern::SCHEME_HTTP, "http://*.example.com/*")); 1187 1188 expected.insert("*.google.com"); 1189 expected.insert("*.example.com"); 1190 1191 scoped_refptr<PermissionSet> perm_set(new PermissionSet( 1192 empty_perms, ManifestPermissionSet(), 1193 explicit_hosts, scriptable_hosts)); 1194 EXPECT_EQ(expected, 1195 permission_message_util::GetDistinctHosts( 1196 perm_set->effective_hosts(), true, true)); 1197 } 1198 1199 { 1200 // We don't display warnings for file URLs because they are off by default. 1201 SCOPED_TRACE("file urls"); 1202 1203 explicit_hosts.ClearPatterns(); 1204 expected.clear(); 1205 1206 explicit_hosts.AddPattern( 1207 URLPattern(URLPattern::SCHEME_FILE, "file:///*")); 1208 1209 EXPECT_EQ(expected, 1210 permission_message_util::GetDistinctHosts( 1211 explicit_hosts, true, true)); 1212 } 1213 } 1214 1215 TEST(PermissionsTest, GetDistinctHosts_ComIsBestRcd) { 1216 URLPatternSet explicit_hosts; 1217 explicit_hosts.AddPattern( 1218 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path")); 1219 explicit_hosts.AddPattern( 1220 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.org/path")); 1221 explicit_hosts.AddPattern( 1222 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path")); 1223 explicit_hosts.AddPattern( 1224 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.net/path")); 1225 explicit_hosts.AddPattern( 1226 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path")); 1227 explicit_hosts.AddPattern( 1228 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path")); 1229 1230 std::set<std::string> expected; 1231 expected.insert("www.foo.com"); 1232 EXPECT_EQ(expected, 1233 permission_message_util::GetDistinctHosts( 1234 explicit_hosts, true, true)); 1235 } 1236 1237 TEST(PermissionsTest, GetDistinctHosts_NetIs2ndBestRcd) { 1238 URLPatternSet explicit_hosts; 1239 explicit_hosts.AddPattern( 1240 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path")); 1241 explicit_hosts.AddPattern( 1242 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.org/path")); 1243 explicit_hosts.AddPattern( 1244 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path")); 1245 explicit_hosts.AddPattern( 1246 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.net/path")); 1247 explicit_hosts.AddPattern( 1248 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path")); 1249 // No http://www.foo.com/path 1250 1251 std::set<std::string> expected; 1252 expected.insert("www.foo.net"); 1253 EXPECT_EQ(expected, 1254 permission_message_util::GetDistinctHosts( 1255 explicit_hosts, true, true)); 1256 } 1257 1258 TEST(PermissionsTest, GetDistinctHosts_OrgIs3rdBestRcd) { 1259 URLPatternSet explicit_hosts; 1260 explicit_hosts.AddPattern( 1261 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path")); 1262 explicit_hosts.AddPattern( 1263 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.org/path")); 1264 explicit_hosts.AddPattern( 1265 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path")); 1266 // No http://www.foo.net/path 1267 explicit_hosts.AddPattern( 1268 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path")); 1269 // No http://www.foo.com/path 1270 1271 std::set<std::string> expected; 1272 expected.insert("www.foo.org"); 1273 EXPECT_EQ(expected, 1274 permission_message_util::GetDistinctHosts( 1275 explicit_hosts, true, true)); 1276 } 1277 1278 TEST(PermissionsTest, GetDistinctHosts_FirstInListIs4thBestRcd) { 1279 URLPatternSet explicit_hosts; 1280 explicit_hosts.AddPattern( 1281 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path")); 1282 // No http://www.foo.org/path 1283 explicit_hosts.AddPattern( 1284 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path")); 1285 // No http://www.foo.net/path 1286 explicit_hosts.AddPattern( 1287 URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path")); 1288 // No http://www.foo.com/path 1289 1290 std::set<std::string> expected; 1291 expected.insert("www.foo.ca"); 1292 EXPECT_EQ(expected, 1293 permission_message_util::GetDistinctHosts( 1294 explicit_hosts, true, true)); 1295 } 1296 1297 TEST(PermissionsTest, IsHostPrivilegeIncrease) { 1298 Manifest::Type type = Manifest::TYPE_EXTENSION; 1299 const PermissionMessageProvider* provider = PermissionMessageProvider::Get(); 1300 ManifestPermissionSet empty_manifest_permissions; 1301 URLPatternSet elist1; 1302 URLPatternSet elist2; 1303 URLPatternSet slist1; 1304 URLPatternSet slist2; 1305 scoped_refptr<PermissionSet> set1; 1306 scoped_refptr<PermissionSet> set2; 1307 APIPermissionSet empty_perms; 1308 elist1.AddPattern( 1309 URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/path")); 1310 elist1.AddPattern( 1311 URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path")); 1312 1313 // Test that the host order does not matter. 1314 elist2.AddPattern( 1315 URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path")); 1316 elist2.AddPattern( 1317 URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/path")); 1318 1319 set1 = new PermissionSet(empty_perms, empty_manifest_permissions, 1320 elist1, slist1); 1321 set2 = new PermissionSet(empty_perms, empty_manifest_permissions, 1322 elist2, slist2); 1323 1324 EXPECT_FALSE(provider->IsPrivilegeIncrease(set1, set2, type)); 1325 EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type)); 1326 1327 // Test that paths are ignored. 1328 elist2.ClearPatterns(); 1329 elist2.AddPattern( 1330 URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/*")); 1331 set2 = new PermissionSet(empty_perms, empty_manifest_permissions, 1332 elist2, slist2); 1333 EXPECT_FALSE(provider->IsPrivilegeIncrease(set1, set2, type)); 1334 EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type)); 1335 1336 // Test that RCDs are ignored. 1337 elist2.ClearPatterns(); 1338 elist2.AddPattern( 1339 URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/*")); 1340 set2 = new PermissionSet(empty_perms, empty_manifest_permissions, 1341 elist2, slist2); 1342 EXPECT_FALSE(provider->IsPrivilegeIncrease(set1, set2, type)); 1343 EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type)); 1344 1345 // Test that subdomain wildcards are handled properly. 1346 elist2.ClearPatterns(); 1347 elist2.AddPattern( 1348 URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com.hk/*")); 1349 set2 = new PermissionSet(empty_perms, empty_manifest_permissions, 1350 elist2, slist2); 1351 EXPECT_TRUE(provider->IsPrivilegeIncrease(set1, set2, type)); 1352 // TODO(jstritar): Does not match subdomains properly. http://crbug.com/65337 1353 // EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type)); 1354 1355 // Test that different domains count as different hosts. 1356 elist2.ClearPatterns(); 1357 elist2.AddPattern( 1358 URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path")); 1359 elist2.AddPattern( 1360 URLPattern(URLPattern::SCHEME_HTTP, "http://www.example.org/path")); 1361 set2 = new PermissionSet(empty_perms, empty_manifest_permissions, 1362 elist2, slist2); 1363 EXPECT_TRUE(provider->IsPrivilegeIncrease(set1, set2, type)); 1364 EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type)); 1365 1366 // Test that different subdomains count as different hosts. 1367 elist2.ClearPatterns(); 1368 elist2.AddPattern( 1369 URLPattern(URLPattern::SCHEME_HTTP, "http://mail.google.com/*")); 1370 set2 = new PermissionSet(empty_perms, empty_manifest_permissions, 1371 elist2, slist2); 1372 EXPECT_TRUE(provider->IsPrivilegeIncrease(set1, set2, type)); 1373 EXPECT_TRUE(provider->IsPrivilegeIncrease(set2, set1, type)); 1374 1375 // Test that platform apps do not have host permissions increases. 1376 type = Manifest::TYPE_PLATFORM_APP; 1377 EXPECT_FALSE(provider->IsPrivilegeIncrease(set1, set2, type)); 1378 EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type)); 1379 } 1380 1381 TEST(PermissionsTest, GetAPIsAsStrings) { 1382 APIPermissionSet apis; 1383 URLPatternSet empty_set; 1384 1385 apis.insert(APIPermission::kProxy); 1386 apis.insert(APIPermission::kBackground); 1387 apis.insert(APIPermission::kNotification); 1388 apis.insert(APIPermission::kTab); 1389 1390 scoped_refptr<PermissionSet> perm_set = new PermissionSet( 1391 apis, ManifestPermissionSet(), empty_set, empty_set); 1392 std::set<std::string> api_names = perm_set->GetAPIsAsStrings(); 1393 1394 // The result is correct if it has the same number of elements 1395 // and we can convert it back to the id set. 1396 EXPECT_EQ(4u, api_names.size()); 1397 EXPECT_EQ(apis, 1398 PermissionsInfo::GetInstance()->GetAllByName(api_names)); 1399 } 1400 1401 TEST(PermissionsTest, IsEmpty) { 1402 APIPermissionSet empty_apis; 1403 URLPatternSet empty_extent; 1404 1405 scoped_refptr<PermissionSet> empty = new PermissionSet(); 1406 EXPECT_TRUE(empty->IsEmpty()); 1407 scoped_refptr<PermissionSet> perm_set; 1408 1409 perm_set = new PermissionSet(empty_apis, ManifestPermissionSet(), 1410 empty_extent, empty_extent); 1411 EXPECT_TRUE(perm_set->IsEmpty()); 1412 1413 APIPermissionSet non_empty_apis; 1414 non_empty_apis.insert(APIPermission::kBackground); 1415 perm_set = new PermissionSet(non_empty_apis, ManifestPermissionSet(), 1416 empty_extent, empty_extent); 1417 EXPECT_FALSE(perm_set->IsEmpty()); 1418 1419 // Try non standard host 1420 URLPatternSet non_empty_extent; 1421 AddPattern(&non_empty_extent, "http://www.google.com/*"); 1422 1423 perm_set = new PermissionSet(empty_apis, ManifestPermissionSet(), 1424 non_empty_extent, empty_extent); 1425 EXPECT_FALSE(perm_set->IsEmpty()); 1426 1427 perm_set = new PermissionSet(empty_apis, ManifestPermissionSet(), 1428 empty_extent, non_empty_extent); 1429 EXPECT_FALSE(perm_set->IsEmpty()); 1430 } 1431 1432 TEST(PermissionsTest, ImpliedPermissions) { 1433 URLPatternSet empty_extent; 1434 APIPermissionSet apis; 1435 apis.insert(APIPermission::kWebRequest); 1436 apis.insert(APIPermission::kFileBrowserHandler); 1437 EXPECT_EQ(2U, apis.size()); 1438 1439 scoped_refptr<PermissionSet> perm_set; 1440 perm_set = new PermissionSet(apis, ManifestPermissionSet(), 1441 empty_extent, empty_extent); 1442 EXPECT_EQ(4U, perm_set->apis().size()); 1443 } 1444 1445 TEST(PermissionsTest, SyncFileSystemPermission) { 1446 scoped_refptr<Extension> extension = LoadManifest( 1447 "permissions", "sync_file_system.json"); 1448 APIPermissionSet apis; 1449 apis.insert(APIPermission::kSyncFileSystem); 1450 EXPECT_TRUE(extension->is_platform_app()); 1451 EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSyncFileSystem)); 1452 std::vector<base::string16> warnings = 1453 PermissionsData::GetPermissionMessageStrings(extension.get()); 1454 EXPECT_TRUE(Contains(warnings, "Store data in your Google Drive account")); 1455 ASSERT_EQ(1u, warnings.size()); 1456 } 1457 1458 // Make sure that we don't crash when we're trying to show the permissions 1459 // even though chrome://thumb (and everything that's not chrome://favicon with 1460 // a chrome:// scheme) is not a valid permission. 1461 // More details here: crbug/246314. 1462 TEST(PermissionsTest, ChromeURLs) { 1463 URLPatternSet allowed_hosts; 1464 allowed_hosts.AddPattern( 1465 URLPattern(URLPattern::SCHEME_ALL, "http://www.google.com/")); 1466 allowed_hosts.AddPattern( 1467 URLPattern(URLPattern::SCHEME_ALL, "chrome://favicon/")); 1468 allowed_hosts.AddPattern( 1469 URLPattern(URLPattern::SCHEME_ALL, "chrome://thumb/")); 1470 scoped_refptr<PermissionSet> permissions( 1471 new PermissionSet(APIPermissionSet(), ManifestPermissionSet(), 1472 allowed_hosts, URLPatternSet())); 1473 PermissionMessageProvider::Get()-> 1474 GetPermissionMessages(permissions, Manifest::TYPE_EXTENSION); 1475 } 1476 1477 TEST(PermissionsTest, IsPrivilegeIncrease_DeclarativeWebRequest) { 1478 scoped_refptr<Extension> extension( 1479 LoadManifest("permissions", "permissions_all_urls.json")); 1480 scoped_refptr<const PermissionSet> permissions( 1481 extension->GetActivePermissions()); 1482 1483 scoped_refptr<Extension> extension_dwr( 1484 LoadManifest("permissions", "web_request_all_host_permissions.json")); 1485 scoped_refptr<const PermissionSet> permissions_dwr( 1486 extension_dwr->GetActivePermissions()); 1487 1488 EXPECT_FALSE(PermissionMessageProvider::Get()-> 1489 IsPrivilegeIncrease(permissions.get(), 1490 permissions_dwr.get(), 1491 extension->GetType())); 1492 } 1493 1494 } // namespace extensions 1495