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 "chrome/common/pepper_permission_util.h"
6
7#include <set>
8#include <string>
9
10#include "chrome/common/extensions/features/feature_channel.h"
11#include "components/crx_file/id_util.h"
12#include "extensions/common/extension_builder.h"
13#include "extensions/common/extension_set.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
16using chrome::IsExtensionOrSharedModuleWhitelisted;
17
18namespace extensions {
19
20namespace {
21
22// Return an extension with |id| which imports a module with the given
23// |import_id|.
24scoped_refptr<Extension> CreateExtensionImportingModule(
25    const std::string& import_id,
26    const std::string& id) {
27  scoped_ptr<base::DictionaryValue> manifest =
28      DictionaryBuilder()
29          .Set("name", "Has Dependent Modules")
30          .Set("version", "1.0")
31          .Set("manifest_version", 2)
32          .Set("import",
33               ListBuilder().Append(DictionaryBuilder().Set("id", import_id)))
34          .Build();
35
36  return ExtensionBuilder()
37      .SetManifest(manifest.Pass())
38      .AddFlags(Extension::FROM_WEBSTORE)
39      .SetID(id)
40      .Build();
41}
42
43}  // namespace
44
45TEST(PepperPermissionUtilTest, ExtensionWhitelisting) {
46  ScopedCurrentChannel current_channel(chrome::VersionInfo::CHANNEL_UNKNOWN);
47  ExtensionSet extensions;
48  std::string whitelisted_id =
49      crx_file::id_util::GenerateId("whitelisted_extension");
50  scoped_ptr<base::DictionaryValue> manifest =
51      DictionaryBuilder()
52          .Set("name", "Whitelisted Extension")
53          .Set("version", "1.0")
54          .Set("manifest_version", 2)
55          .Build();
56  scoped_refptr<Extension> ext = ExtensionBuilder()
57                                     .SetManifest(manifest.Pass())
58                                     .SetID(whitelisted_id)
59                                     .Build();
60  extensions.Insert(ext);
61  std::set<std::string> whitelist;
62  std::string url = std::string("chrome-extension://") + whitelisted_id +
63                    std::string("/manifest.nmf");
64  std::string bad_scheme_url =
65      std::string("http://") + whitelisted_id + std::string("/manifest.nmf");
66  std::string bad_host_url = std::string("chrome-extension://") +
67                             crx_file::id_util::GenerateId("bad_host");
68  std::string("/manifest.nmf");
69
70  EXPECT_FALSE(
71      IsExtensionOrSharedModuleWhitelisted(GURL(url), &extensions, whitelist));
72  whitelist.insert(whitelisted_id);
73  EXPECT_TRUE(
74      IsExtensionOrSharedModuleWhitelisted(GURL(url), &extensions, whitelist));
75  EXPECT_FALSE(IsExtensionOrSharedModuleWhitelisted(
76      GURL(bad_scheme_url), &extensions, whitelist));
77  EXPECT_FALSE(IsExtensionOrSharedModuleWhitelisted(
78      GURL(bad_host_url), &extensions, whitelist));
79}
80
81TEST(PepperPermissionUtilTest, SharedModuleWhitelisting) {
82  ScopedCurrentChannel current_channel(chrome::VersionInfo::CHANNEL_UNKNOWN);
83  ExtensionSet extensions;
84  std::string whitelisted_id = crx_file::id_util::GenerateId("extension_id");
85  std::string bad_id = crx_file::id_util::GenerateId("bad_id");
86
87  scoped_ptr<base::DictionaryValue> shared_module_manifest =
88      DictionaryBuilder()
89          .Set("name", "Whitelisted Shared Module")
90          .Set("version", "1.0")
91          .Set("manifest_version", 2)
92          .Set("export",
93               DictionaryBuilder()
94                   .Set("resources", ListBuilder().Append("*"))
95                   // Add the extension to the whitelist.  This
96                   // restricts import to |whitelisted_id| only.
97                   .Set("whitelist", ListBuilder().Append(whitelisted_id)))
98          .Build();
99  scoped_refptr<Extension> shared_module =
100      ExtensionBuilder().SetManifest(shared_module_manifest.Pass()).Build();
101
102  scoped_refptr<Extension> ext =
103      CreateExtensionImportingModule(shared_module->id(), whitelisted_id);
104  std::string extension_url =
105      std::string("chrome-extension://") + ext->id() + std::string("/foo.html");
106
107  std::set<std::string> whitelist;
108  // Important: whitelist *only* the shared module.
109  whitelist.insert(shared_module->id());
110
111  extensions.Insert(ext);
112  // This should fail because shared_module is not in the set of extensions.
113  EXPECT_FALSE(IsExtensionOrSharedModuleWhitelisted(
114      GURL(extension_url), &extensions, whitelist));
115  extensions.Insert(shared_module);
116  EXPECT_TRUE(IsExtensionOrSharedModuleWhitelisted(
117      GURL(extension_url), &extensions, whitelist));
118  scoped_refptr<Extension> not_in_sm_whitelist =
119      CreateExtensionImportingModule(shared_module->id(), bad_id);
120  std::string not_in_sm_whitelist_url = std::string("chrome-extension://") +
121                                        not_in_sm_whitelist->id() +
122                                        std::string("/foo.html");
123
124  extensions.Insert(not_in_sm_whitelist);
125  // This should succeed, even though |not_in_sm_whitelist| is not whitelisted
126  // to use shared_module, because the pepper permission utility does not care
127  // about that whitelist.  It is possible to install against the whitelist as
128  // an unpacked extension.
129  EXPECT_TRUE(IsExtensionOrSharedModuleWhitelisted(
130      GURL(not_in_sm_whitelist_url), &extensions, whitelist));
131
132  // Note that the whitelist should be empty after this call, so tests checking
133  // for failure to import will fail because of this.
134  whitelist.erase(shared_module->id());
135  EXPECT_FALSE(IsExtensionOrSharedModuleWhitelisted(
136      GURL(extension_url), &extensions, whitelist));
137}
138
139}  // namespace extensions
140