1 // Copyright 2019 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/browser/extensions/api/messaging/native_messaging_launch_from_native.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/path_service.h"
11 #include "base/test/values_test_util.h"
12 #include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
13 #include "chrome/test/base/testing_profile.h"
14 #include "components/version_info/version_info.h"
15 #include "content/public/test/browser_task_environment.h"
16 #include "extensions/browser/event_router.h"
17 #include "extensions/browser/event_router_factory.h"
18 #include "extensions/browser/extension_prefs.h"
19 #include "extensions/browser/extension_registry.h"
20 #include "extensions/common/extension_paths.h"
21 #include "extensions/common/features/feature_channel.h"
22 #include "extensions/common/manifest_constants.h"
23 #include "extensions/common/value_builder.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace extensions {
27 namespace {
28
29 class MockEventRouter : public EventRouter {
30 public:
MockEventRouter(content::BrowserContext * browser_context,ExtensionPrefs * extension_prefs,const bool * has_listener_result)31 MockEventRouter(content::BrowserContext* browser_context,
32 ExtensionPrefs* extension_prefs,
33 const bool* has_listener_result)
34 : EventRouter(browser_context, extension_prefs),
35 has_listener_result_(has_listener_result) {
36 DCHECK(has_listener_result_);
37 }
38
ExtensionHasEventListener(const std::string & extension_id,const std::string & event_name) const39 bool ExtensionHasEventListener(const std::string& extension_id,
40 const std::string& event_name) const override {
41 return *has_listener_result_;
42 }
43
44 private:
45 const bool* has_listener_result_;
46 };
47
BuildMockEventRouter(const bool * has_listener_result,content::BrowserContext * context)48 std::unique_ptr<KeyedService> BuildMockEventRouter(
49 const bool* has_listener_result,
50 content::BrowserContext* context) {
51 return std::make_unique<MockEventRouter>(
52 context, ExtensionPrefs::Get(context), has_listener_result);
53 }
54
55 class ExtensionSupportsConnectionFromNativeAppTest : public ::testing::Test {
56 public:
ExtensionSupportsConnectionFromNativeAppTest()57 ExtensionSupportsConnectionFromNativeAppTest()
58 : channel_(version_info::Channel::DEV) {}
59
SetUp()60 void SetUp() override {
61 EventRouterFactory::GetInstance()->SetTestingFactory(
62 &profile_,
63 base::BindRepeating(&BuildMockEventRouter, &has_listener_result_));
64 }
65
66 protected:
RegisterExtension(bool natively_connectable,bool transient_background_permission,bool native_messaging_permission)67 void RegisterExtension(bool natively_connectable,
68 bool transient_background_permission,
69 bool native_messaging_permission) {
70 DictionaryBuilder manifest_builder(
71 static_cast<base::DictionaryValue&&>(base::test::ParseJson(R"(
72 {
73 "version": "1.0.0.0",
74 "manifest_version": 2,
75 "name": "native messaging test",
76 "description": "native messaging test",
77 "background": {
78 "scripts": ["test.js"],
79 "persistent": false
80 }
81 }
82 )")));
83
84 if (natively_connectable) {
85 ListBuilder natively_connectable_hosts;
86 natively_connectable_hosts.Append(
87 ScopedTestNativeMessagingHost::kHostName);
88
89 natively_connectable_hosts.Append(
90 ScopedTestNativeMessagingHost::
91 kSupportsNativeInitiatedConnectionsHostName);
92 manifest_builder.Set(manifest_keys::kNativelyConnectable,
93 natively_connectable_hosts.Build());
94 }
95
96 ListBuilder permissions;
97 if (transient_background_permission) {
98 permissions.Append("transientBackground");
99 }
100 if (native_messaging_permission) {
101 permissions.Append("nativeMessaging");
102 }
103 manifest_builder.Set(manifest_keys::kPermissions, permissions.Build());
104
105 base::FilePath path;
106 EXPECT_TRUE(base::PathService::Get(DIR_TEST_DATA, &path));
107
108 std::string error;
109 scoped_refptr<Extension> extension(
110 Extension::Create(path, Manifest::INTERNAL, *manifest_builder.Build(),
111 Extension::NO_FLAGS, &error));
112 ASSERT_TRUE(extension.get()) << error;
113 ExtensionRegistry::Get(&profile_)->AddEnabled(extension);
114 extension_id_ = extension->id();
115 }
116
117 ScopedCurrentChannel channel_;
118 content::BrowserTaskEnvironment task_environment_;
119 bool has_listener_result_ = true;
120 TestingProfile profile_;
121 std::string extension_id_;
122 };
123
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,Success)124 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, Success) {
125 ASSERT_NO_FATAL_FAILURE(RegisterExtension(true, true, true));
126
127 EXPECT_TRUE(ExtensionSupportsConnectionFromNativeApp(
128 extension_id_,
129 ScopedTestNativeMessagingHost::
130 kSupportsNativeInitiatedConnectionsHostName,
131 &profile_, false));
132 }
133
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,NoOnConnectNative)134 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, NoOnConnectNative) {
135 ASSERT_NO_FATAL_FAILURE(RegisterExtension(true, true, true));
136 has_listener_result_ = false;
137
138 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
139 extension_id_,
140 ScopedTestNativeMessagingHost::
141 kSupportsNativeInitiatedConnectionsHostName,
142 &profile_, false));
143 }
144
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,OffTheRecordProfile)145 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, OffTheRecordProfile) {
146 auto* off_the_record_profile = profile_.GetPrimaryOTRProfile();
147 ASSERT_NO_FATAL_FAILURE(RegisterExtension(true, true, true));
148
149 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
150 extension_id_,
151 ScopedTestNativeMessagingHost::
152 kSupportsNativeInitiatedConnectionsHostName,
153 off_the_record_profile, false));
154 }
155
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,NotNativelyConnectable)156 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, NotNativelyConnectable) {
157 ASSERT_NO_FATAL_FAILURE(RegisterExtension(false, true, true));
158
159 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
160 extension_id_,
161 ScopedTestNativeMessagingHost::
162 kSupportsNativeInitiatedConnectionsHostName,
163 &profile_, false));
164 }
165
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,NotTransientBackground)166 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, NotTransientBackground) {
167 ASSERT_NO_FATAL_FAILURE(RegisterExtension(true, false, true));
168
169 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
170 extension_id_,
171 ScopedTestNativeMessagingHost::
172 kSupportsNativeInitiatedConnectionsHostName,
173 &profile_, false));
174 }
175
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,NotNativeMessaging)176 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, NotNativeMessaging) {
177 ASSERT_NO_FATAL_FAILURE(RegisterExtension(true, true, false));
178
179 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
180 extension_id_,
181 ScopedTestNativeMessagingHost::
182 kSupportsNativeInitiatedConnectionsHostName,
183 &profile_, false));
184 }
185
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,NativeMessagingOnly)186 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, NativeMessagingOnly) {
187 ASSERT_NO_FATAL_FAILURE(RegisterExtension(false, false, true));
188
189 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
190 extension_id_,
191 ScopedTestNativeMessagingHost::
192 kSupportsNativeInitiatedConnectionsHostName,
193 &profile_, false));
194 }
195
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,TransientBackgroundOnly)196 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, TransientBackgroundOnly) {
197 ASSERT_NO_FATAL_FAILURE(RegisterExtension(false, true, false));
198
199 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
200 extension_id_,
201 ScopedTestNativeMessagingHost::
202 kSupportsNativeInitiatedConnectionsHostName,
203 &profile_, false));
204 }
205
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,NativelyConnectableOnly)206 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, NativelyConnectableOnly) {
207 ASSERT_NO_FATAL_FAILURE(RegisterExtension(true, false, false));
208
209 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
210 extension_id_,
211 ScopedTestNativeMessagingHost::
212 kSupportsNativeInitiatedConnectionsHostName,
213 &profile_, false));
214 }
215
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,NoPermissions)216 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, NoPermissions) {
217 ASSERT_NO_FATAL_FAILURE(RegisterExtension(false, false, false));
218 has_listener_result_ = false;
219
220 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
221 extension_id_,
222 ScopedTestNativeMessagingHost::
223 kSupportsNativeInitiatedConnectionsHostName,
224 &profile_, false));
225 }
226
TEST_F(ExtensionSupportsConnectionFromNativeAppTest,UnknownExtension)227 TEST_F(ExtensionSupportsConnectionFromNativeAppTest, UnknownExtension) {
228 EXPECT_FALSE(ExtensionSupportsConnectionFromNativeApp(
229 "fake extension id",
230 ScopedTestNativeMessagingHost::
231 kSupportsNativeInitiatedConnectionsHostName,
232 &profile_, false));
233 }
234
235 } // namespace
236 } // namespace extensions
237