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