1 // Copyright (c) 2011 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/message_loop.h" 6 #include "base/path_service.h" 7 #include "chrome/browser/extensions/extension_info_map.h" 8 #include "chrome/common/chrome_paths.h" 9 #include "chrome/common/extensions/extension.h" 10 #include "content/browser/browser_thread.h" 11 #include "content/common/json_value_serializer.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 namespace keys = extension_manifest_keys; 15 16 namespace { 17 18 class ExtensionInfoMapTest : public testing::Test { 19 public: 20 ExtensionInfoMapTest() 21 : ui_thread_(BrowserThread::UI, &message_loop_), 22 io_thread_(BrowserThread::IO, &message_loop_) { 23 } 24 25 private: 26 MessageLoop message_loop_; 27 BrowserThread ui_thread_; 28 BrowserThread io_thread_; 29 }; 30 31 // Returns a barebones test Extension object with the given name. 32 static scoped_refptr<Extension> CreateExtension(const std::string& name) { 33 #if defined(OS_WIN) 34 FilePath path(FILE_PATH_LITERAL("c:\\foo")); 35 #elif defined(OS_POSIX) 36 FilePath path(FILE_PATH_LITERAL("/foo")); 37 #endif 38 39 DictionaryValue manifest; 40 manifest.SetString(keys::kVersion, "1.0.0.0"); 41 manifest.SetString(keys::kName, name); 42 43 std::string error; 44 scoped_refptr<Extension> extension = Extension::Create( 45 path.AppendASCII(name), Extension::INVALID, manifest, 46 Extension::STRICT_ERROR_CHECKS, &error); 47 EXPECT_TRUE(extension) << error; 48 49 return extension; 50 } 51 52 static scoped_refptr<Extension> LoadManifest(const std::string& dir, 53 const std::string& test_file) { 54 FilePath path; 55 PathService::Get(chrome::DIR_TEST_DATA, &path); 56 path = path.AppendASCII("extensions") 57 .AppendASCII(dir) 58 .AppendASCII(test_file); 59 60 JSONFileValueSerializer serializer(path); 61 scoped_ptr<Value> result(serializer.Deserialize(NULL, NULL)); 62 if (!result.get()) 63 return NULL; 64 65 std::string error; 66 scoped_refptr<Extension> extension = Extension::Create( 67 path, Extension::INVALID, *static_cast<DictionaryValue*>(result.get()), 68 Extension::STRICT_ERROR_CHECKS, &error); 69 EXPECT_TRUE(extension) << error; 70 71 return extension; 72 } 73 74 // Test that the ExtensionInfoMap handles refcounting properly. 75 TEST_F(ExtensionInfoMapTest, RefCounting) { 76 scoped_refptr<ExtensionInfoMap> info_map(new ExtensionInfoMap()); 77 78 // New extensions should have a single reference holding onto them. 79 scoped_refptr<Extension> extension1(CreateExtension("extension1")); 80 scoped_refptr<Extension> extension2(CreateExtension("extension2")); 81 scoped_refptr<Extension> extension3(CreateExtension("extension3")); 82 EXPECT_TRUE(extension1->HasOneRef()); 83 EXPECT_TRUE(extension2->HasOneRef()); 84 EXPECT_TRUE(extension3->HasOneRef()); 85 86 // Add a ref to each extension and give it to the info map. 87 info_map->AddExtension(extension1); 88 info_map->AddExtension(extension2); 89 info_map->AddExtension(extension3); 90 91 // Release extension1, and the info map should have the only ref. 92 const Extension* weak_extension1 = extension1; 93 extension1 = NULL; 94 EXPECT_TRUE(weak_extension1->HasOneRef()); 95 96 // Remove extension2, and the extension2 object should have the only ref. 97 info_map->RemoveExtension(extension2->id(), UnloadedExtensionInfo::UNINSTALL); 98 EXPECT_TRUE(extension2->HasOneRef()); 99 100 // Delete the info map, and the extension3 object should have the only ref. 101 info_map = NULL; 102 EXPECT_TRUE(extension3->HasOneRef()); 103 } 104 105 // Tests that we can query a few extension properties from the ExtensionInfoMap. 106 TEST_F(ExtensionInfoMapTest, Properties) { 107 scoped_refptr<ExtensionInfoMap> info_map(new ExtensionInfoMap()); 108 109 scoped_refptr<Extension> extension1(CreateExtension("extension1")); 110 scoped_refptr<Extension> extension2(CreateExtension("extension2")); 111 112 info_map->AddExtension(extension1); 113 info_map->AddExtension(extension2); 114 115 EXPECT_EQ(extension1->name(), 116 info_map->GetNameForExtension(extension1->id())); 117 EXPECT_EQ(extension2->name(), 118 info_map->GetNameForExtension(extension2->id())); 119 120 EXPECT_EQ(extension1->path().value(), 121 info_map->GetPathForExtension(extension1->id()).value()); 122 EXPECT_EQ(extension2->path().value(), 123 info_map->GetPathForExtension(extension2->id()).value()); 124 } 125 126 // Tests CheckURLAccessToExtensionPermission given both extension and app URLs. 127 TEST_F(ExtensionInfoMapTest, CheckPermissions) { 128 scoped_refptr<ExtensionInfoMap> info_map(new ExtensionInfoMap()); 129 130 scoped_refptr<Extension> app(LoadManifest("manifest_tests", 131 "valid_app.json")); 132 scoped_refptr<Extension> extension(LoadManifest("manifest_tests", 133 "tabs_extension.json")); 134 135 GURL app_url("http://www.google.com/mail/foo.html"); 136 ASSERT_TRUE(app->is_app()); 137 ASSERT_TRUE(app->web_extent().ContainsURL(app_url)); 138 139 info_map->AddExtension(app); 140 info_map->AddExtension(extension); 141 142 // The app should have the notifications permission, either from a 143 // chrome-extension URL or from its web extent. 144 EXPECT_TRUE(info_map->CheckURLAccessToExtensionPermission( 145 app->GetResourceURL("a.html"), Extension::kNotificationPermission)); 146 EXPECT_TRUE(info_map->CheckURLAccessToExtensionPermission( 147 app_url, Extension::kNotificationPermission)); 148 EXPECT_FALSE(info_map->CheckURLAccessToExtensionPermission( 149 app_url, Extension::kTabPermission)); 150 151 // The extension should have the tabs permission. 152 EXPECT_TRUE(info_map->CheckURLAccessToExtensionPermission( 153 extension->GetResourceURL("a.html"), Extension::kTabPermission)); 154 EXPECT_FALSE(info_map->CheckURLAccessToExtensionPermission( 155 extension->GetResourceURL("a.html"), Extension::kNotificationPermission)); 156 157 // Random URL should not have any permissions. 158 EXPECT_FALSE(info_map->CheckURLAccessToExtensionPermission( 159 GURL("http://evil.com/a.html"), Extension::kNotificationPermission)); 160 EXPECT_FALSE(info_map->CheckURLAccessToExtensionPermission( 161 GURL("http://evil.com/a.html"), Extension::kTabPermission)); 162 } 163 164 } // namespace 165