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