1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/memory/ref_counted.h"
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/memory/scoped_ptr.h"
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/strings/string16.h"
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/values.h"
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/extension_service.h"
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/extensions/extension_service_test_base.h"
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/pending_extension_manager.h"
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/shared_module_service.h"
130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "chrome/common/extensions/features/feature_channel.h"
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h"
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/browser/extension_registry.h"
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "extensions/browser/install_flag.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/uninstall_reason.h"
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension_builder.h"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/value_builder.h"
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "sync/api/string_ordinal.h"
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace extensions {
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace {
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Return an extension with |id| which imports a module with the given
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// |import_id|.
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochscoped_refptr<Extension> CreateExtensionImportingModule(
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& import_id,
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& id,
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& version) {
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DictionaryBuilder builder;
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  builder.Set("name", "Has Dependent Modules")
34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         .Set("version", version)
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         .Set("manifest_version", 2);
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!import_id.empty()) {
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    builder.Set("import",
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                ListBuilder().Append(DictionaryBuilder().Set("id", import_id)));
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<base::DictionaryValue> manifest = builder.Build();
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return ExtensionBuilder().SetManifest(manifest.Pass())
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                           .AddFlags(Extension::FROM_WEBSTORE)
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                           .SetID(id)
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                           .Build();
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass SharedModuleServiceUnitTest : public ExtensionServiceTestBase {
510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) public:
520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  SharedModuleServiceUnitTest() :
530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      // The "export" key is open for dev-channel only, but unit tests
540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      // run as stable channel on the official Windows build.
550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      current_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {}
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch protected:
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void SetUp() OVERRIDE;
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Install an extension and notify the ExtensionService.
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  testing::AssertionResult InstallExtension(const Extension* extension,
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            bool is_update);
620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  ScopedCurrentChannel current_channel_;
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid SharedModuleServiceUnitTest::SetUp() {
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ExtensionServiceTestBase::SetUp();
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  InitializeGoodInstalledExtensionService();
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  service()->Init();
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochtesting::AssertionResult SharedModuleServiceUnitTest::InstallExtension(
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Extension* extension,
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool is_update) {
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const Extension* old = registry()->GetExtensionById(
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extension->id(),
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ExtensionRegistry::ENABLED);
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Verify the extension is not already installed, if it is not update.
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!is_update) {
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (old)
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return testing::AssertionFailure() << "Extension already installed.";
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!old)
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return testing::AssertionFailure() << "The extension does not exist.";
86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Notify the service that the extension is installed. This adds it to the
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // registry, notifies interested parties, etc.
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  service()->OnExtensionInstalled(
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      extension, syncer::StringOrdinal(), kInstallFlagInstallImmediately);
92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Verify that the extension is now installed.
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!registry()->GetExtensionById(extension->id(),
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                    ExtensionRegistry::ENABLED)) {
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return testing::AssertionFailure() << "Could not install extension.";
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return testing::AssertionSuccess();
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(SharedModuleServiceUnitTest, AddDependentSharedModules) {
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Create an extension that has a dependency.
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string import_id = crx_file::id_util::GenerateId("id");
10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string extension_id = crx_file::id_util::GenerateId("extension_id");
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<Extension> extension =
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateExtensionImportingModule(import_id, extension_id, "1.0");
108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  PendingExtensionManager* pending_extension_manager =
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      service()->pending_extension_manager();
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Verify that we don't currently want to install the imported module.
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(pending_extension_manager->IsIdPending(import_id));
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Try to satisfy imports for the extension. This should queue the imported
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // module's installation.
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  service()->shared_module_service()->SatisfyImports(extension.get());
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_TRUE(pending_extension_manager->IsIdPending(import_id));
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(SharedModuleServiceUnitTest, PruneSharedModulesOnUninstall) {
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Create a module which exports a resource, and install it.
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<base::DictionaryValue> manifest =
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DictionaryBuilder()
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          .Set("name", "Shared Module")
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          .Set("version", "1.0")
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          .Set("manifest_version", 2)
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          .Set("export",
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               DictionaryBuilder().Set("resources",
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                       ListBuilder().Append("foo.js"))).Build();
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<Extension> shared_module =
13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      ExtensionBuilder()
13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .SetManifest(manifest.Pass())
13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .AddFlags(Extension::FROM_WEBSTORE)
13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .SetID(crx_file::id_util::GenerateId("shared_module"))
13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .Build();
137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(shared_module.get(), false));
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string extension_id = crx_file::id_util::GenerateId("extension_id");
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Create and install an extension that imports our new module.
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<Extension> importing_extension =
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateExtensionImportingModule(shared_module->id(), extension_id, "1.0");
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(importing_extension.get(), false));
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Uninstall the extension that imports our module.
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::string16 error;
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  service()->UninstallExtension(importing_extension->id(),
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                extensions::UNINSTALL_REASON_FOR_TESTING,
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                base::Bind(&base::DoNothing),
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &error);
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_TRUE(error.empty());
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Since the module was only referenced by that single extension, it should
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // have been uninstalled as a side-effect of uninstalling the extension that
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // depended upon it.
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_FALSE(registry()->GetExtensionById(shared_module->id(),
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                            ExtensionRegistry::EVERYTHING));
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
161116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(SharedModuleServiceUnitTest, PruneSharedModulesOnUpdate) {
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Create two modules which export a resource, and install them.
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<base::DictionaryValue> manifest_1 =
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DictionaryBuilder()
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .Set("name", "Shared Module 1")
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .Set("version", "1.0")
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .Set("manifest_version", 2)
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .Set("export",
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch               DictionaryBuilder().Set("resources",
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       ListBuilder().Append("foo.js"))).Build();
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<Extension> shared_module_1 =
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      ExtensionBuilder()
17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .SetManifest(manifest_1.Pass())
17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .AddFlags(Extension::FROM_WEBSTORE)
17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .SetID(crx_file::id_util::GenerateId("shared_module_1"))
17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .Build();
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(shared_module_1.get(), false));
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<base::DictionaryValue> manifest_2 =
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DictionaryBuilder()
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .Set("name", "Shared Module 2")
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .Set("version", "1.0")
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .Set("manifest_version", 2)
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .Set("export",
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch               DictionaryBuilder().Set("resources",
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       ListBuilder().Append("foo.js"))).Build();
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<Extension> shared_module_2 =
18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      ExtensionBuilder()
18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .SetManifest(manifest_2.Pass())
19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .AddFlags(Extension::FROM_WEBSTORE)
19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .SetID(crx_file::id_util::GenerateId("shared_module_2"))
19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .Build();
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(shared_module_2.get(), false));
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string extension_id = crx_file::id_util::GenerateId("extension_id");
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Create and install an extension v1.0 that imports our new module 1.
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<Extension> importing_extension_1 =
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateExtensionImportingModule(shared_module_1->id(),
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     extension_id,
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     "1.0");
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(importing_extension_1.get(), false));
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Create and install a new version of the extension that imports our new
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // module 2.
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<Extension> importing_extension_2 =
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateExtensionImportingModule(shared_module_2->id(),
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     extension_id,
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     "1.1");
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(importing_extension_2.get(), true));
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Since the extension v1.1 depends the module 2 insteand module 1.
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // So the module 1 should be uninstalled.
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(registry()->GetExtensionById(shared_module_1->id(),
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            ExtensionRegistry::EVERYTHING));
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(registry()->GetExtensionById(shared_module_2->id(),
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            ExtensionRegistry::EVERYTHING));
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Create and install a new version of the extension that does not import any
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // module.
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<Extension> importing_extension_3 =
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateExtensionImportingModule("", extension_id, "1.2");
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(importing_extension_3.get(), true));
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Since the extension v1.2 does not depend any module, so the all models
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // should have been uninstalled.
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(registry()->GetExtensionById(shared_module_1->id(),
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            ExtensionRegistry::EVERYTHING));
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(registry()->GetExtensionById(shared_module_2->id(),
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            ExtensionRegistry::EVERYTHING));
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)TEST_F(SharedModuleServiceUnitTest, WhitelistedImports) {
23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string whitelisted_id = crx_file::id_util::GenerateId("whitelisted");
23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string nonwhitelisted_id =
23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      crx_file::id_util::GenerateId("nonwhitelisted");
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Create a module which exports to a restricted whitelist.
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> manifest =
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DictionaryBuilder()
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          .Set("name", "Shared Module")
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          .Set("version", "1.0")
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          .Set("manifest_version", 2)
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          .Set("export",
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)               DictionaryBuilder().Set("whitelist",
246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       ListBuilder()
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                           .Append(whitelisted_id))
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  .Set("resources",
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       ListBuilder().Append("*"))).Build();
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<Extension> shared_module =
25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      ExtensionBuilder()
25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .SetManifest(manifest.Pass())
25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .AddFlags(Extension::FROM_WEBSTORE)
25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .SetID(crx_file::id_util::GenerateId("shared_module"))
25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          .Build();
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(shared_module.get(), false));
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Create and install an extension with the whitelisted ID.
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<Extension> whitelisted_extension =
261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateExtensionImportingModule(shared_module->id(),
262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     whitelisted_id,
263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     "1.0");
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(whitelisted_extension.get(), false));
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Try to install an extension with an ID that is not whitelisted.
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<Extension> nonwhitelisted_extension =
268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateExtensionImportingModule(shared_module->id(),
269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     nonwhitelisted_id,
270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     "1.0");
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // This should succeed because only CRX installer (and by extension the
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // WebStore Installer) checks the shared module whitelist.  InstallExtension
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // bypasses the whitelist check because the SharedModuleService does not
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // care about whitelists.
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(InstallExtension(nonwhitelisted_extension.get(), false));
276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace extensions
279