1 // Copyright 2016 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 "components/crx_file/id_util.h"
6 #include "extensions/common/extension.h"
7 #include "extensions/common/extension_builder.h"
8 #include "extensions/common/extension_messages.h"
9 #include "extensions/common/manifest_handlers/permissions_parser.h"
10 #include "extensions/common/permissions/extensions_api_permissions.h"
11 #include "extensions/common/permissions/permissions_data.h"
12 #include "extensions/common/value_builder.h"
13 #include "ipc/ipc_message.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 namespace extensions {
17 
18 namespace {
19 
CompareExtension(const Extension & extension1,const Extension & extension2)20 void CompareExtension(const Extension& extension1,
21                       const Extension& extension2) {
22   EXPECT_EQ(extension1.name(), extension2.name());
23   EXPECT_EQ(extension1.id(), extension2.id());
24   EXPECT_EQ(extension1.path(), extension2.path());
25   EXPECT_EQ(extension1.permissions_data()->active_permissions(),
26             extension2.permissions_data()->active_permissions());
27   EXPECT_TRUE(extension1.manifest()->Equals(extension2.manifest()));
28   const PermissionsData::TabPermissionsMap& second_tab_permissions =
29       extension2.permissions_data()->tab_specific_permissions();
30   for (const auto& tab_permissions :
31        extension1.permissions_data()->tab_specific_permissions()) {
32     ASSERT_NE(0u, second_tab_permissions.count(tab_permissions.first));
33     EXPECT_EQ(*tab_permissions.second,
34               *(second_tab_permissions.at(tab_permissions.first)))
35         << tab_permissions.first;
36   }
37   EXPECT_EQ(extension1.permissions_data()->policy_blocked_hosts(),
38             extension2.permissions_data()->policy_blocked_hosts());
39   EXPECT_EQ(extension1.permissions_data()->policy_allowed_hosts(),
40             extension2.permissions_data()->policy_allowed_hosts());
41 }
42 
AddPattern(const std::string & pattern,URLPatternSet * extent)43 void AddPattern(const std::string& pattern, URLPatternSet* extent) {
44   URLPattern parsed(URLPattern::SCHEME_ALL);
45   parsed.Parse(pattern);
46   extent->AddPattern(parsed);
47 }
48 
49 }  // namespace
50 
TEST(ExtensionMessageTypesTest,TestLoadedParams)51 TEST(ExtensionMessageTypesTest, TestLoadedParams) {
52   std::unique_ptr<base::DictionaryValue> manifest =
53       DictionaryBuilder()
54           .Set("name", "extension")
55           .Set("description", "an extension")
56           .Set("permissions", ListBuilder().Append("alarms").Build())
57           .Set("manifest_version", 2)
58           .Set("version", "0.1")
59           .Build();
60   scoped_refptr<const Extension> extension =
61       ExtensionBuilder()
62           .SetManifest(std::move(manifest))
63           .SetID(crx_file::id_util::GenerateId("foo"))
64           .Build();
65   const PermissionSet& required_permissions =
66       PermissionsParser::GetRequiredPermissions(extension.get());
67   LOG(WARNING) << required_permissions.apis().size();
68   EXPECT_TRUE(
69       extension->permissions_data()->HasAPIPermission(APIPermission::kAlarms));
70   {
71     APIPermissionSet tab_permissions;
72     tab_permissions.insert(APIPermission::kDns);
73     extension->permissions_data()->UpdateTabSpecificPermissions(
74         1, PermissionSet(std::move(tab_permissions), ManifestPermissionSet(),
75                          URLPatternSet(), URLPatternSet()));
76   }
77   URLPatternSet runtime_blocked_hosts;
78   AddPattern("*://*.example.com/*", &runtime_blocked_hosts);
79   URLPatternSet runtime_allowed_hosts;
80   AddPattern("*://good.example.com/*", &runtime_allowed_hosts);
81   extension->permissions_data()->SetPolicyHostRestrictions(
82       runtime_blocked_hosts, runtime_allowed_hosts);
83 
84   ExtensionMsg_Loaded_Params params_in(extension.get(), true, base::nullopt);
85   EXPECT_EQ(extension->id(), params_in.id);
86 
87   {
88     // First, test just converting back to an extension.
89     std::string error;
90     // TODO(devlin): Move this to a renderer-specific location in order to
91     // better enforce this restriction.
92 
93     // The logic is only called in the render context that's why it's
94     // safe to pass 0 as context_id.
95     scoped_refptr<const Extension> extension_out =
96         params_in.ConvertToExtension(0, &error);
97     EXPECT_TRUE(error.empty());
98     ASSERT_TRUE(extension_out);
99     CompareExtension(*extension, *extension_out);
100   }
101 
102   {
103     // Second, try bouncing the params and then converting back.
104     IPC::Message msg;
105     IPC::ParamTraits<ExtensionMsg_Loaded_Params>::Write(&msg, params_in);
106     ExtensionMsg_Loaded_Params params_out;
107     base::PickleIterator iter(msg);
108     EXPECT_TRUE(IPC::ParamTraits<ExtensionMsg_Loaded_Params>::Read(
109         &msg, &iter, &params_out));
110 
111     EXPECT_EQ(params_in.id, params_out.id);
112     EXPECT_TRUE(params_in.manifest.Equals(&params_out.manifest));
113     EXPECT_EQ(params_in.location, params_out.location);
114     EXPECT_EQ(params_in.path, params_out.path);
115     EXPECT_EQ(params_in.creation_flags, params_out.creation_flags);
116     // Permission equaliy on the params will be tested through the conversion to
117     // an extension.
118 
119     std::string error;
120     scoped_refptr<const Extension> extension_out =
121         params_out.ConvertToExtension(0, &error);
122     EXPECT_TRUE(error.empty());
123     ASSERT_TRUE(extension_out);
124     CompareExtension(*extension, *extension_out);
125   }
126 }
127 
128 }  // namespace extensions
129