Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(211)

Side by Side Diff: chrome/browser/extensions/shared_module_service_unittest.cc

Issue 386033002: Prune shared extendion module after extension updating. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix review issues Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/memory/ref_counted.h" 5 #include "base/memory/ref_counted.h"
6 #include "base/memory/scoped_ptr.h" 6 #include "base/memory/scoped_ptr.h"
7 #include "base/strings/string16.h" 7 #include "base/strings/string16.h"
8 #include "base/values.h" 8 #include "base/values.h"
9 #include "chrome/browser/extensions/extension_service.h" 9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_service_test_base.h" 10 #include "chrome/browser/extensions/extension_service_test_base.h"
11 #include "chrome/browser/extensions/pending_extension_manager.h" 11 #include "chrome/browser/extensions/pending_extension_manager.h"
12 #include "chrome/browser/extensions/shared_module_service.h" 12 #include "chrome/browser/extensions/shared_module_service.h"
13 #include "chrome/common/extensions/features/feature_channel.h" 13 #include "chrome/common/extensions/features/feature_channel.h"
14 #include "extensions/browser/extension_registry.h" 14 #include "extensions/browser/extension_registry.h"
15 #include "extensions/browser/install_flag.h" 15 #include "extensions/browser/install_flag.h"
16 #include "extensions/common/extension_builder.h" 16 #include "extensions/common/extension_builder.h"
17 #include "extensions/common/id_util.h" 17 #include "extensions/common/id_util.h"
18 #include "extensions/common/value_builder.h" 18 #include "extensions/common/value_builder.h"
19 #include "sync/api/string_ordinal.h" 19 #include "sync/api/string_ordinal.h"
20 20
21 namespace extensions { 21 namespace extensions {
22 22
23 namespace { 23 namespace {
24 24
25 // Return an extension with |id| which imports a module with the given 25 // Return an extension with |id| which imports a module with the given
26 // |import_id|. 26 // |import_id|.
27 scoped_refptr<Extension> CreateExtensionImportingModule( 27 scoped_refptr<Extension> CreateExtensionImportingModule(
28 const std::string& import_id, const std::string& id) { 28 const std::string& import_id,
29 scoped_ptr<base::DictionaryValue> manifest = 29 const std::string& id,
30 DictionaryBuilder() 30 const std::string& version) {
31 .Set("name", "Has Dependent Modules") 31 DictionaryBuilder builder;
32 .Set("version", "1.0") 32 builder.Set("name", "Has Dependent Modules")
33 .Set("manifest_version", 2) 33 .Set("version", version)
34 .Set("import", 34 .Set("manifest_version", 2);
35 ListBuilder().Append(DictionaryBuilder().Set("id", import_id))) 35 if (!import_id.empty()) {
36 .Build(); 36 builder.Set("import",
37 ListBuilder().Append(DictionaryBuilder().Set("id", import_id)));
38 }
39 scoped_ptr<base::DictionaryValue> manifest = builder.Build();
37 40
38 return ExtensionBuilder().SetManifest(manifest.Pass()) 41 return ExtensionBuilder().SetManifest(manifest.Pass())
39 .AddFlags(Extension::FROM_WEBSTORE) 42 .AddFlags(Extension::FROM_WEBSTORE)
40 .SetID(id) 43 .SetID(id)
41 .Build(); 44 .Build();
42 } 45 }
43 46
44 } // namespace 47 } // namespace
45 48
46 class SharedModuleServiceUnitTest : public ExtensionServiceTestBase { 49 class SharedModuleServiceUnitTest : public ExtensionServiceTestBase {
47 public: 50 public:
48 SharedModuleServiceUnitTest() : 51 SharedModuleServiceUnitTest() :
49 // The "export" key is open for dev-channel only, but unit tests 52 // The "export" key is open for dev-channel only, but unit tests
50 // run as stable channel on the official Windows build. 53 // run as stable channel on the official Windows build.
51 current_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {} 54 current_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {}
52 protected: 55 protected:
53 virtual void SetUp() OVERRIDE; 56 virtual void SetUp() OVERRIDE;
54 57
55 // Install an extension and notify the ExtensionService. 58 // Install an extension and notify the ExtensionService.
56 testing::AssertionResult InstallExtension(const Extension* extension); 59 testing::AssertionResult InstallExtension(const Extension* extension,
60 bool is_update);
57 ScopedCurrentChannel current_channel_; 61 ScopedCurrentChannel current_channel_;
58 }; 62 };
59 63
60 void SharedModuleServiceUnitTest::SetUp() { 64 void SharedModuleServiceUnitTest::SetUp() {
61 ExtensionServiceTestBase::SetUp(); 65 ExtensionServiceTestBase::SetUp();
62 InitializeGoodInstalledExtensionService(); 66 InitializeGoodInstalledExtensionService();
63 service_->Init(); 67 service()->Init();
64 } 68 }
65 69
66 testing::AssertionResult SharedModuleServiceUnitTest::InstallExtension( 70 testing::AssertionResult SharedModuleServiceUnitTest::InstallExtension(
67 const Extension* extension) { 71 const Extension* extension,
68 // Verify the extension is not already installed. 72 bool is_update) {
69 if (registry()->GetExtensionById(extension->id(), 73
70 ExtensionRegistry::ENABLED)) { 74 const Extension* old = registry()->GetExtensionById(
71 return testing::AssertionFailure() << "Extension already installed."; 75 extension->id(),
76 ExtensionRegistry::ENABLED);
77
78 // Verify the extension is not already installed, if it is not update.
79 if (!is_update) {
80 if (old)
81 return testing::AssertionFailure() << "Extension already installed.";
82 } else {
83 if (!old)
84 return testing::AssertionFailure() << "The extension does not exist.";
72 } 85 }
73 86
74 // Notify the service that the extension is installed. This adds it to the 87 // Notify the service that the extension is installed. This adds it to the
75 // registry, notifies interested parties, etc. 88 // registry, notifies interested parties, etc.
76 service_->OnExtensionInstalled( 89 service()->OnExtensionInstalled(
77 extension, syncer::StringOrdinal(), kInstallFlagInstallImmediately); 90 extension, syncer::StringOrdinal(), kInstallFlagInstallImmediately);
78 91
79 // Verify that the extension is now installed. 92 // Verify that the extension is now installed.
80 if (!registry()->GetExtensionById(extension->id(), 93 if (!registry()->GetExtensionById(extension->id(),
81 ExtensionRegistry::ENABLED)) { 94 ExtensionRegistry::ENABLED)) {
82 return testing::AssertionFailure() << "Could not install extension."; 95 return testing::AssertionFailure() << "Could not install extension.";
83 } 96 }
84 97
85 return testing::AssertionSuccess(); 98 return testing::AssertionSuccess();
86 } 99 }
87 100
88 TEST_F(SharedModuleServiceUnitTest, AddDependentSharedModules) { 101 TEST_F(SharedModuleServiceUnitTest, AddDependentSharedModules) {
89 // Create an extension that has a dependency. 102 // Create an extension that has a dependency.
90 std::string import_id = id_util::GenerateId("id"); 103 std::string import_id = id_util::GenerateId("id");
91 std::string extension_id = id_util::GenerateId("extension_id"); 104 std::string extension_id = id_util::GenerateId("extension_id");
92 scoped_refptr<Extension> extension = 105 scoped_refptr<Extension> extension =
93 CreateExtensionImportingModule(import_id, extension_id); 106 CreateExtensionImportingModule(import_id, extension_id, "1.0");
94 107
95 PendingExtensionManager* pending_extension_manager = 108 PendingExtensionManager* pending_extension_manager =
96 service_->pending_extension_manager(); 109 service()->pending_extension_manager();
97 110
98 // Verify that we don't currently want to install the imported module. 111 // Verify that we don't currently want to install the imported module.
99 EXPECT_FALSE(pending_extension_manager->IsIdPending(import_id)); 112 EXPECT_FALSE(pending_extension_manager->IsIdPending(import_id));
100 113
101 // Try to satisfy imports for the extension. This should queue the imported 114 // Try to satisfy imports for the extension. This should queue the imported
102 // module's installation. 115 // module's installation.
103 service_->shared_module_service()->SatisfyImports(extension); 116 service()->shared_module_service()->SatisfyImports(extension);
104 EXPECT_TRUE(pending_extension_manager->IsIdPending(import_id)); 117 EXPECT_TRUE(pending_extension_manager->IsIdPending(import_id));
105 } 118 }
106 119
107 TEST_F(SharedModuleServiceUnitTest, PruneSharedModulesOnUninstall) { 120 TEST_F(SharedModuleServiceUnitTest, PruneSharedModulesOnUninstall) {
108 // Create a module which exports a resource, and install it. 121 // Create a module which exports a resource, and install it.
109 scoped_ptr<base::DictionaryValue> manifest = 122 scoped_ptr<base::DictionaryValue> manifest =
110 DictionaryBuilder() 123 DictionaryBuilder()
111 .Set("name", "Shared Module") 124 .Set("name", "Shared Module")
112 .Set("version", "1.0") 125 .Set("version", "1.0")
113 .Set("manifest_version", 2) 126 .Set("manifest_version", 2)
114 .Set("export", 127 .Set("export",
115 DictionaryBuilder().Set("resources", 128 DictionaryBuilder().Set("resources",
116 ListBuilder().Append("foo.js"))).Build(); 129 ListBuilder().Append("foo.js"))).Build();
117 scoped_refptr<Extension> shared_module = 130 scoped_refptr<Extension> shared_module =
118 ExtensionBuilder().SetManifest(manifest.Pass()) 131 ExtensionBuilder().SetManifest(manifest.Pass())
119 .AddFlags(Extension::FROM_WEBSTORE) 132 .AddFlags(Extension::FROM_WEBSTORE)
120 .SetID(id_util::GenerateId("shared_module")) 133 .SetID(id_util::GenerateId("shared_module"))
121 .Build(); 134 .Build();
122 135
123 EXPECT_TRUE(InstallExtension(shared_module)); 136 EXPECT_TRUE(InstallExtension(shared_module, false));
124 137
125 std::string extension_id = id_util::GenerateId("extension_id"); 138 std::string extension_id = id_util::GenerateId("extension_id");
126 // Create and install an extension that imports our new module. 139 // Create and install an extension that imports our new module.
127 scoped_refptr<Extension> importing_extension = 140 scoped_refptr<Extension> importing_extension =
128 CreateExtensionImportingModule(shared_module->id(), extension_id); 141 CreateExtensionImportingModule(shared_module->id(), extension_id, "1.0");
129 EXPECT_TRUE(InstallExtension(importing_extension)); 142 EXPECT_TRUE(InstallExtension(importing_extension, false));
130 143
131 // Uninstall the extension that imports our module. 144 // Uninstall the extension that imports our module.
132 base::string16 error; 145 base::string16 error;
133 service_->UninstallExtension(importing_extension->id(), 146 service()->UninstallExtension(importing_extension->id(),
134 ExtensionService::UNINSTALL_REASON_FOR_TESTING, 147 ExtensionService::UNINSTALL_REASON_FOR_TESTING,
135 &error); 148 &error);
136 EXPECT_TRUE(error.empty()); 149 EXPECT_TRUE(error.empty());
137 150
138 // Since the module was only referenced by that single extension, it should 151 // Since the module was only referenced by that single extension, it should
139 // have been uninstalled as a side-effect of uninstalling the extension that 152 // have been uninstalled as a side-effect of uninstalling the extension that
140 // depended upon it. 153 // depended upon it.
141 EXPECT_FALSE(registry()->GetExtensionById(shared_module->id(), 154 EXPECT_FALSE(registry()->GetExtensionById(shared_module->id(),
142 ExtensionRegistry::EVERYTHING)); 155 ExtensionRegistry::EVERYTHING));
143 } 156 }
144 157
158 TEST_F(SharedModuleServiceUnitTest, PruneSharedModulesOnUpdate) {
159 // Create two modules which export a resource, and install them.
160 scoped_ptr<base::DictionaryValue> manifest_1 =
161 DictionaryBuilder()
162 .Set("name", "Shared Module 1")
163 .Set("version", "1.0")
164 .Set("manifest_version", 2)
165 .Set("export",
166 DictionaryBuilder().Set("resources",
167 ListBuilder().Append("foo.js"))).Build();
168 scoped_refptr<Extension> shared_module_1 =
169 ExtensionBuilder().SetManifest(manifest_1.Pass())
170 .AddFlags(Extension::FROM_WEBSTORE)
171 .SetID(id_util::GenerateId("shared_module_1"))
172 .Build();
173 EXPECT_TRUE(InstallExtension(shared_module_1, false));
174
175 scoped_ptr<base::DictionaryValue> manifest_2 =
176 DictionaryBuilder()
177 .Set("name", "Shared Module 2")
178 .Set("version", "1.0")
179 .Set("manifest_version", 2)
180 .Set("export",
181 DictionaryBuilder().Set("resources",
182 ListBuilder().Append("foo.js"))).Build();
183 scoped_refptr<Extension> shared_module_2 =
184 ExtensionBuilder().SetManifest(manifest_2.Pass())
185 .AddFlags(Extension::FROM_WEBSTORE)
186 .SetID(id_util::GenerateId("shared_module_2"))
187 .Build();
188 EXPECT_TRUE(InstallExtension(shared_module_2, false));
189
190 std::string extension_id = id_util::GenerateId("extension_id");
191
192 // Create and install an extension v1.0 that imports our new module 1.
193 scoped_refptr<Extension> importing_extension_1 =
194 CreateExtensionImportingModule(shared_module_1->id(),
195 extension_id,
196 "1.0");
197 EXPECT_TRUE(InstallExtension(importing_extension_1, false));
198
199 // Create and install a new version of the extension that imports our new
200 // module 2.
201 scoped_refptr<Extension> importing_extension_2 =
202 CreateExtensionImportingModule(shared_module_2->id(),
203 extension_id,
204 "1.1");
205 EXPECT_TRUE(InstallExtension(importing_extension_2, true));
206
207 // Since the extension v1.1 depends the module 2 insteand module 1.
208 // So the module 1 should be uninstalled.
209 EXPECT_FALSE(registry()->GetExtensionById(shared_module_1->id(),
210 ExtensionRegistry::EVERYTHING));
211 EXPECT_TRUE(registry()->GetExtensionById(shared_module_2->id(),
212 ExtensionRegistry::EVERYTHING));
213
214 // Create and install a new version of the extension that does not import any
215 // module.
216 scoped_refptr<Extension> importing_extension_3 =
217 CreateExtensionImportingModule("", extension_id, "1.2");
218 EXPECT_TRUE(InstallExtension(importing_extension_3, true));
219
220 // Since the extension v1.2 does not depend any module, so the all models
221 // should have been uninstalled.
222 EXPECT_FALSE(registry()->GetExtensionById(shared_module_1->id(),
223 ExtensionRegistry::EVERYTHING));
224 EXPECT_FALSE(registry()->GetExtensionById(shared_module_2->id(),
225 ExtensionRegistry::EVERYTHING));
226
227 }
228
145 TEST_F(SharedModuleServiceUnitTest, WhitelistedImports) { 229 TEST_F(SharedModuleServiceUnitTest, WhitelistedImports) {
146 std::string whitelisted_id = id_util::GenerateId("whitelisted"); 230 std::string whitelisted_id = id_util::GenerateId("whitelisted");
147 std::string nonwhitelisted_id = id_util::GenerateId("nonwhitelisted"); 231 std::string nonwhitelisted_id = id_util::GenerateId("nonwhitelisted");
148 // Create a module which exports to a restricted whitelist. 232 // Create a module which exports to a restricted whitelist.
149 scoped_ptr<base::DictionaryValue> manifest = 233 scoped_ptr<base::DictionaryValue> manifest =
150 DictionaryBuilder() 234 DictionaryBuilder()
151 .Set("name", "Shared Module") 235 .Set("name", "Shared Module")
152 .Set("version", "1.0") 236 .Set("version", "1.0")
153 .Set("manifest_version", 2) 237 .Set("manifest_version", 2)
154 .Set("export", 238 .Set("export",
155 DictionaryBuilder().Set("whitelist", 239 DictionaryBuilder().Set("whitelist",
156 ListBuilder() 240 ListBuilder()
157 .Append(whitelisted_id)) 241 .Append(whitelisted_id))
158 .Set("resources", 242 .Set("resources",
159 ListBuilder().Append("*"))).Build(); 243 ListBuilder().Append("*"))).Build();
160 scoped_refptr<Extension> shared_module = 244 scoped_refptr<Extension> shared_module =
161 ExtensionBuilder().SetManifest(manifest.Pass()) 245 ExtensionBuilder().SetManifest(manifest.Pass())
162 .AddFlags(Extension::FROM_WEBSTORE) 246 .AddFlags(Extension::FROM_WEBSTORE)
163 .SetID(id_util::GenerateId("shared_module")) 247 .SetID(id_util::GenerateId("shared_module"))
164 .Build(); 248 .Build();
165 249
166 EXPECT_TRUE(InstallExtension(shared_module)); 250 EXPECT_TRUE(InstallExtension(shared_module, false));
167 251
168 // Create and install an extension with the whitelisted ID. 252 // Create and install an extension with the whitelisted ID.
169 scoped_refptr<Extension> whitelisted_extension = 253 scoped_refptr<Extension> whitelisted_extension =
170 CreateExtensionImportingModule(shared_module->id(), whitelisted_id); 254 CreateExtensionImportingModule(shared_module->id(),
171 EXPECT_TRUE(InstallExtension(whitelisted_extension)); 255 whitelisted_id,
256 "1.0");
257 EXPECT_TRUE(InstallExtension(whitelisted_extension, false));
172 258
173 // Try to install an extension with an ID that is not whitelisted. 259 // Try to install an extension with an ID that is not whitelisted.
174 scoped_refptr<Extension> nonwhitelisted_extension = 260 scoped_refptr<Extension> nonwhitelisted_extension =
175 CreateExtensionImportingModule(shared_module->id(), nonwhitelisted_id); 261 CreateExtensionImportingModule(shared_module->id(),
176 EXPECT_FALSE(InstallExtension(nonwhitelisted_extension)); 262 nonwhitelisted_id,
263 "1.0");
264 EXPECT_FALSE(InstallExtension(nonwhitelisted_extension, false));
177 } 265 }
178 266
179 } // namespace extensions 267 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/shared_module_service.cc ('k') | chrome/browser/extensions/webstore_installer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698