shared_module_service_unittest.cc revision 0de6073388f4e2780db8536178b129cd8f6ab386
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/ref_counted.h" 6#include "base/memory/scoped_ptr.h" 7#include "base/strings/string16.h" 8#include "base/values.h" 9#include "chrome/browser/extensions/extension_service.h" 10#include "chrome/browser/extensions/extension_service_unittest.h" 11#include "chrome/browser/extensions/pending_extension_manager.h" 12#include "chrome/browser/extensions/shared_module_service.h" 13#include "chrome/common/extensions/features/feature_channel.h" 14#include "extensions/browser/extension_registry.h" 15#include "extensions/common/extension_builder.h" 16#include "extensions/common/id_util.h" 17#include "extensions/common/value_builder.h" 18#include "sync/api/string_ordinal.h" 19 20namespace extensions { 21 22namespace { 23 24// Return an extension with |id| which imports a module with the given 25// |import_id|. 26scoped_refptr<Extension> CreateExtensionImportingModule( 27 const std::string& import_id, const std::string& id) { 28 scoped_ptr<base::DictionaryValue> manifest = 29 DictionaryBuilder() 30 .Set("name", "Has Dependent Modules") 31 .Set("version", "1.0") 32 .Set("manifest_version", 2) 33 .Set("import", 34 ListBuilder().Append(DictionaryBuilder().Set("id", import_id))) 35 .Build(); 36 37 return ExtensionBuilder().SetManifest(manifest.Pass()) 38 .AddFlags(Extension::FROM_WEBSTORE) 39 .SetID(id) 40 .Build(); 41} 42 43} // namespace 44 45class SharedModuleServiceUnitTest : public ExtensionServiceTestBase { 46 public: 47 SharedModuleServiceUnitTest() : 48 // The "export" key is open for dev-channel only, but unit tests 49 // run as stable channel on the official Windows build. 50 current_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {} 51 protected: 52 virtual void SetUp() OVERRIDE; 53 54 // Install an extension and notify the ExtensionService. 55 testing::AssertionResult InstallExtension(const Extension* extension); 56 ScopedCurrentChannel current_channel_; 57}; 58 59void SharedModuleServiceUnitTest::SetUp() { 60 ExtensionServiceTestBase::SetUp(); 61 InitializeGoodInstalledExtensionService(); 62 service_->Init(); 63} 64 65testing::AssertionResult SharedModuleServiceUnitTest::InstallExtension( 66 const Extension* extension) { 67 // Verify the extension is not already installed. 68 if (registry_->GetExtensionById(extension->id(), 69 ExtensionRegistry::ENABLED)) { 70 return testing::AssertionFailure() << "Extension already installed."; 71 } 72 73 // Notify the service that the extension is installed. This adds it to the 74 // registry, notifies interested parties, etc. 75 service_->OnExtensionInstalled(extension, 76 syncer::StringOrdinal(), 77 false, // No requirement errors. 78 NOT_BLACKLISTED, 79 false); // Don't wait for idle. 80 81 // Verify that the extension is now installed. 82 if (!registry_->GetExtensionById(extension->id(), 83 ExtensionRegistry::ENABLED)) { 84 return testing::AssertionFailure() << "Could not install extension."; 85 } 86 87 return testing::AssertionSuccess(); 88} 89 90TEST_F(SharedModuleServiceUnitTest, AddDependentSharedModules) { 91 // Create an extension that has a dependency. 92 std::string import_id = id_util::GenerateId("id"); 93 std::string extension_id = id_util::GenerateId("extension_id"); 94 scoped_refptr<Extension> extension = 95 CreateExtensionImportingModule(import_id, extension_id); 96 97 PendingExtensionManager* pending_extension_manager = 98 service_->pending_extension_manager(); 99 100 // Verify that we don't currently want to install the imported module. 101 EXPECT_FALSE(pending_extension_manager->IsIdPending(import_id)); 102 103 // Try to satisfy imports for the extension. This should queue the imported 104 // module's installation. 105 service_->shared_module_service()->SatisfyImports(extension); 106 EXPECT_TRUE(pending_extension_manager->IsIdPending(import_id)); 107} 108 109TEST_F(SharedModuleServiceUnitTest, PruneSharedModulesOnUninstall) { 110 // Create a module which exports a resource, and install it. 111 scoped_ptr<base::DictionaryValue> manifest = 112 DictionaryBuilder() 113 .Set("name", "Shared Module") 114 .Set("version", "1.0") 115 .Set("manifest_version", 2) 116 .Set("export", 117 DictionaryBuilder().Set("resources", 118 ListBuilder().Append("foo.js"))).Build(); 119 scoped_refptr<Extension> shared_module = 120 ExtensionBuilder().SetManifest(manifest.Pass()) 121 .AddFlags(Extension::FROM_WEBSTORE) 122 .SetID(id_util::GenerateId("shared_module")) 123 .Build(); 124 125 EXPECT_TRUE(InstallExtension(shared_module)); 126 127 std::string extension_id = id_util::GenerateId("extension_id"); 128 // Create and install an extension that imports our new module. 129 scoped_refptr<Extension> importing_extension = 130 CreateExtensionImportingModule(shared_module->id(), extension_id); 131 EXPECT_TRUE(InstallExtension(importing_extension)); 132 133 // Uninstall the extension that imports our module. 134 base::string16 error; 135 service_->UninstallExtension(importing_extension->id(), 136 false, // Not external uninstall. 137 &error); 138 EXPECT_TRUE(error.empty()); 139 140 // Since the module was only referenced by that single extension, it should 141 // have been uninstalled as a side-effect of uninstalling the extension that 142 // depended upon it. 143 EXPECT_FALSE(registry_->GetExtensionById(shared_module->id(), 144 ExtensionRegistry::EVERYTHING)); 145} 146 147TEST_F(SharedModuleServiceUnitTest, WhitelistedImports) { 148 std::string whitelisted_id = id_util::GenerateId("whitelisted"); 149 std::string nonwhitelisted_id = id_util::GenerateId("nonwhitelisted"); 150 // Create a module which exports to a restricted whitelist. 151 scoped_ptr<base::DictionaryValue> manifest = 152 DictionaryBuilder() 153 .Set("name", "Shared Module") 154 .Set("version", "1.0") 155 .Set("manifest_version", 2) 156 .Set("export", 157 DictionaryBuilder().Set("whitelist", 158 ListBuilder() 159 .Append(whitelisted_id)) 160 .Set("resources", 161 ListBuilder().Append("*"))).Build(); 162 scoped_refptr<Extension> shared_module = 163 ExtensionBuilder().SetManifest(manifest.Pass()) 164 .AddFlags(Extension::FROM_WEBSTORE) 165 .SetID(id_util::GenerateId("shared_module")) 166 .Build(); 167 168 EXPECT_TRUE(InstallExtension(shared_module)); 169 170 // Create and install an extension with the whitelisted ID. 171 scoped_refptr<Extension> whitelisted_extension = 172 CreateExtensionImportingModule(shared_module->id(), whitelisted_id); 173 EXPECT_TRUE(InstallExtension(whitelisted_extension)); 174 175 // Try to install an extension with an ID that is not whitelisted. 176 scoped_refptr<Extension> nonwhitelisted_extension = 177 CreateExtensionImportingModule(shared_module->id(), nonwhitelisted_id); 178 EXPECT_FALSE(InstallExtension(nonwhitelisted_extension)); 179} 180 181} // namespace extensions 182