1 // Copyright 2018 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/win/conflicts/incompatible_applications_updater.h"
6 
7 #include <map>
8 #include <string>
9 #include <utility>
10 
11 #include "base/optional.h"
12 #include "base/run_loop.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/test/scoped_feature_list.h"
15 #include "base/test/test_reg_util_win.h"
16 #include "base/win/registry.h"
17 #include "base/win/windows_version.h"
18 #include "chrome/browser/win/conflicts/module_info.h"
19 #include "chrome/browser/win/conflicts/module_list_filter.h"
20 #include "chrome/common/chrome_features.h"
21 #include "chrome/test/base/scoped_testing_local_state.h"
22 #include "chrome/test/base/testing_browser_process.h"
23 #include "content/public/common/process_type.h"
24 #include "content/public/test/browser_task_environment.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 
27 namespace {
28 
29 // Mocks an empty whitelist and blacklist.
30 class MockModuleListFilter : public ModuleListFilter {
31  public:
32   MockModuleListFilter() = default;
33 
IsWhitelisted(base::StringPiece module_basename_hash,base::StringPiece module_code_id_hash) const34   bool IsWhitelisted(base::StringPiece module_basename_hash,
35                      base::StringPiece module_code_id_hash) const override {
36     return false;
37   }
38 
IsBlacklisted(const ModuleInfoKey & module_key,const ModuleInfoData & module_data) const39   std::unique_ptr<chrome::conflicts::BlacklistAction> IsBlacklisted(
40       const ModuleInfoKey& module_key,
41       const ModuleInfoData& module_data) const override {
42     return nullptr;
43   }
44 
45  private:
46   ~MockModuleListFilter() override = default;
47 
48   DISALLOW_COPY_AND_ASSIGN(MockModuleListFilter);
49 };
50 
51 class MockInstalledApplications : public InstalledApplications {
52  public:
53   MockInstalledApplications() = default;
54   ~MockInstalledApplications() override = default;
55 
AddIncompatibleApplication(const base::FilePath & file_path,ApplicationInfo application_info)56   void AddIncompatibleApplication(const base::FilePath& file_path,
57                                   ApplicationInfo application_info) {
58     applications_.insert({file_path, std::move(application_info)});
59   }
60 
GetInstalledApplications(const base::FilePath & file,std::vector<ApplicationInfo> * applications) const61   bool GetInstalledApplications(
62       const base::FilePath& file,
63       std::vector<ApplicationInfo>* applications) const override {
64     auto range = applications_.equal_range(file);
65 
66     if (std::distance(range.first, range.second) == 0)
67       return false;
68 
69     for (auto it = range.first; it != range.second; ++it)
70       applications->push_back(it->second);
71     return true;
72   }
73 
74  private:
75   std::multimap<base::FilePath, ApplicationInfo> applications_;
76 
77   DISALLOW_COPY_AND_ASSIGN(MockInstalledApplications);
78 };
79 
80 constexpr wchar_t kCertificatePath[] = L"CertificatePath";
81 constexpr wchar_t kCertificateSubject[] = L"CertificateSubject";
82 
83 constexpr wchar_t kDllPath1[] = L"c:\\path\\to\\module.dll";
84 constexpr wchar_t kDllPath2[] = L"c:\\some\\shellextension.dll";
85 
86 // Returns a new ModuleInfoData marked as loaded into the browser process but
87 // otherwise empty.
CreateLoadedModuleInfoData()88 ModuleInfoData CreateLoadedModuleInfoData() {
89   ModuleInfoData module_data;
90   module_data.module_properties |= ModuleInfoData::kPropertyLoadedModule;
91   module_data.process_types |= ProcessTypeToBit(content::PROCESS_TYPE_BROWSER);
92   module_data.inspection_result = base::make_optional<ModuleInspectionResult>();
93   return module_data;
94 }
95 
96 // Returns a new ModuleInfoData marked as loaded into the process with a
97 // CertificateInfo that matches kCertificateSubject.
CreateSignedLoadedModuleInfoData()98 ModuleInfoData CreateSignedLoadedModuleInfoData() {
99   ModuleInfoData module_data = CreateLoadedModuleInfoData();
100 
101   module_data.inspection_result->certificate_info.type =
102       CertificateInfo::Type::CERTIFICATE_IN_FILE;
103   module_data.inspection_result->certificate_info.path =
104       base::FilePath(kCertificatePath);
105   module_data.inspection_result->certificate_info.subject = kCertificateSubject;
106 
107   return module_data;
108 }
109 
110 }  // namespace
111 
112 class IncompatibleApplicationsUpdaterTest : public testing::Test,
113                                             public ModuleDatabaseEventSource {
114  protected:
IncompatibleApplicationsUpdaterTest()115   IncompatibleApplicationsUpdaterTest()
116       : dll1_(kDllPath1),
117         dll2_(kDllPath2),
118         scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()),
119         module_list_filter_(base::MakeRefCounted<MockModuleListFilter>()) {
120     exe_certificate_info_.type = CertificateInfo::Type::CERTIFICATE_IN_FILE;
121     exe_certificate_info_.path = base::FilePath(kCertificatePath);
122     exe_certificate_info_.subject = kCertificateSubject;
123   }
124 
SetUp()125   void SetUp() override {
126     ASSERT_NO_FATAL_FAILURE(
127         registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
128 
129     scoped_feature_list_.InitAndEnableFeature(
130         features::kIncompatibleApplicationsWarning);
131   }
132 
133   enum class Option {
134     ADD_REGISTRY_ENTRY,
135     NO_REGISTRY_ENTRY,
136   };
AddIncompatibleApplication(const base::FilePath & injected_module_path,const base::string16 & application_name,Option option)137   void AddIncompatibleApplication(const base::FilePath& injected_module_path,
138                                   const base::string16& application_name,
139                                   Option option) {
140     static constexpr wchar_t kUninstallRegKeyFormat[] =
141         L"dummy\\uninstall\\%ls";
142 
143     const base::string16 registry_key_path =
144         base::StringPrintf(kUninstallRegKeyFormat, application_name.c_str());
145 
146     installed_applications_.AddIncompatibleApplication(
147         injected_module_path, {application_name, HKEY_CURRENT_USER,
148                                registry_key_path, KEY_WOW64_32KEY});
149 
150     if (option == Option::ADD_REGISTRY_ENTRY) {
151       base::win::RegKey reg_key(HKEY_CURRENT_USER, registry_key_path.c_str(),
152                                 KEY_WOW64_32KEY | KEY_CREATE_SUB_KEY);
153     }
154   }
155 
156   std::unique_ptr<IncompatibleApplicationsUpdater>
CreateIncompatibleApplicationsUpdater()157   CreateIncompatibleApplicationsUpdater() {
158     return std::make_unique<IncompatibleApplicationsUpdater>(
159         this, exe_certificate_info_, module_list_filter_,
160         installed_applications_, false);
161   }
162 
163   // ModuleDatabaseEventSource:
AddObserver(ModuleDatabaseObserver * observer)164   void AddObserver(ModuleDatabaseObserver* observer) override {}
RemoveObserver(ModuleDatabaseObserver * observer)165   void RemoveObserver(ModuleDatabaseObserver* observer) override {}
166 
RunLoopUntilIdle()167   void RunLoopUntilIdle() { base::RunLoop().RunUntilIdle(); }
168 
169   const base::FilePath dll1_;
170   const base::FilePath dll2_;
171 
172  private:
173   content::BrowserTaskEnvironment task_environment_;
174   ScopedTestingLocalState scoped_testing_local_state_;
175   registry_util::RegistryOverrideManager registry_override_manager_;
176   base::test::ScopedFeatureList scoped_feature_list_;
177 
178   CertificateInfo exe_certificate_info_;
179   scoped_refptr<MockModuleListFilter> module_list_filter_;
180   MockInstalledApplications installed_applications_;
181 
182   DISALLOW_COPY_AND_ASSIGN(IncompatibleApplicationsUpdaterTest);
183 };
184 
185 // Tests that when the Local State cache is empty, no incompatible applications
186 // are returned.
TEST_F(IncompatibleApplicationsUpdaterTest,EmptyCache)187 TEST_F(IncompatibleApplicationsUpdaterTest, EmptyCache) {
188   if (base::win::GetVersion() < base::win::Version::WIN10)
189     return;
190 
191   EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
192   EXPECT_TRUE(IncompatibleApplicationsUpdater::GetCachedApplications().empty());
193 }
194 
195 // IncompatibleApplicationsUpdater doesn't do anything when there is no
196 // registered installed applications.
TEST_F(IncompatibleApplicationsUpdaterTest,NoIncompatibleApplications)197 TEST_F(IncompatibleApplicationsUpdaterTest, NoIncompatibleApplications) {
198   if (base::win::GetVersion() < base::win::Version::WIN10)
199     return;
200 
201   auto incompatible_applications_updater =
202       CreateIncompatibleApplicationsUpdater();
203 
204   // Simulate some arbitrary module loading into the process.
205   incompatible_applications_updater->OnNewModuleFound(
206       ModuleInfoKey(dll1_, 0, 0), CreateLoadedModuleInfoData());
207   incompatible_applications_updater->OnModuleDatabaseIdle();
208   RunLoopUntilIdle();
209 
210   EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
211   EXPECT_TRUE(IncompatibleApplicationsUpdater::GetCachedApplications().empty());
212 }
213 
TEST_F(IncompatibleApplicationsUpdaterTest,NoTiedApplications)214 TEST_F(IncompatibleApplicationsUpdaterTest, NoTiedApplications) {
215   if (base::win::GetVersion() < base::win::Version::WIN10)
216     return;
217 
218   auto incompatible_applications_updater =
219       CreateIncompatibleApplicationsUpdater();
220 
221   // Simulate the module loading into the process.
222   ModuleInfoKey module_key(dll1_, 0, 0);
223   incompatible_applications_updater->OnNewModuleFound(
224       module_key, CreateLoadedModuleInfoData());
225   incompatible_applications_updater->OnModuleDatabaseIdle();
226   RunLoopUntilIdle();
227 
228   EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
229   EXPECT_TRUE(IncompatibleApplicationsUpdater::GetCachedApplications().empty());
230 
231   EXPECT_EQ(
232       incompatible_applications_updater->GetModuleWarningDecision(module_key),
233       IncompatibleApplicationsUpdater::ModuleWarningDecision::
234           kNoTiedApplication);
235 }
236 
TEST_F(IncompatibleApplicationsUpdaterTest,OneIncompatibility)237 TEST_F(IncompatibleApplicationsUpdaterTest, OneIncompatibility) {
238   if (base::win::GetVersion() < base::win::Version::WIN10)
239     return;
240 
241   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
242 
243   auto incompatible_applications_updater =
244       CreateIncompatibleApplicationsUpdater();
245 
246   // Simulate the module loading into the process.
247   ModuleInfoKey module_key(dll1_, 0, 0);
248   incompatible_applications_updater->OnNewModuleFound(
249       module_key, CreateLoadedModuleInfoData());
250   incompatible_applications_updater->OnModuleDatabaseIdle();
251   RunLoopUntilIdle();
252 
253   EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
254   auto application_names =
255       IncompatibleApplicationsUpdater::GetCachedApplications();
256   ASSERT_EQ(1u, application_names.size());
257   EXPECT_EQ(L"Foo", application_names[0].info.name);
258   EXPECT_EQ(
259       incompatible_applications_updater->GetModuleWarningDecision(module_key),
260       IncompatibleApplicationsUpdater::ModuleWarningDecision::kIncompatible);
261 }
262 
TEST_F(IncompatibleApplicationsUpdaterTest,SameModuleMultipleApplications)263 TEST_F(IncompatibleApplicationsUpdaterTest, SameModuleMultipleApplications) {
264   if (base::win::GetVersion() < base::win::Version::WIN10)
265     return;
266 
267   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
268   AddIncompatibleApplication(dll1_, L"Bar", Option::ADD_REGISTRY_ENTRY);
269 
270   auto incompatible_applications_updater =
271       CreateIncompatibleApplicationsUpdater();
272 
273   // Simulate the module loading into the process.
274   ModuleInfoKey module_key(dll1_, 0, 0);
275   incompatible_applications_updater->OnNewModuleFound(
276       module_key, CreateLoadedModuleInfoData());
277   incompatible_applications_updater->OnModuleDatabaseIdle();
278   RunLoopUntilIdle();
279 
280   EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
281   auto application_names =
282       IncompatibleApplicationsUpdater::GetCachedApplications();
283   ASSERT_EQ(2u, application_names.size());
284   EXPECT_EQ(
285       incompatible_applications_updater->GetModuleWarningDecision(module_key),
286       IncompatibleApplicationsUpdater::ModuleWarningDecision::kIncompatible);
287 }
288 
TEST_F(IncompatibleApplicationsUpdaterTest,MultipleCallsToOnModuleDatabaseIdle)289 TEST_F(IncompatibleApplicationsUpdaterTest,
290        MultipleCallsToOnModuleDatabaseIdle) {
291   if (base::win::GetVersion() < base::win::Version::WIN10)
292     return;
293 
294   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
295   AddIncompatibleApplication(dll2_, L"Bar", Option::ADD_REGISTRY_ENTRY);
296 
297   auto incompatible_applications_updater =
298       CreateIncompatibleApplicationsUpdater();
299 
300   // Simulate the module loading into the process.
301   ModuleInfoKey module_key1(dll1_, 0, 0);
302   incompatible_applications_updater->OnNewModuleFound(
303       module_key1, CreateLoadedModuleInfoData());
304   incompatible_applications_updater->OnModuleDatabaseIdle();
305   RunLoopUntilIdle();
306 
307   // Add an additional module.
308   ModuleInfoKey module_key2(dll2_, 0, 0);
309   incompatible_applications_updater->OnNewModuleFound(
310       module_key2, CreateLoadedModuleInfoData());
311   incompatible_applications_updater->OnModuleDatabaseIdle();
312   RunLoopUntilIdle();
313 
314   EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
315   auto application_names =
316       IncompatibleApplicationsUpdater::GetCachedApplications();
317   ASSERT_EQ(2u, application_names.size());
318   EXPECT_EQ(
319       incompatible_applications_updater->GetModuleWarningDecision(module_key1),
320       IncompatibleApplicationsUpdater::ModuleWarningDecision::kIncompatible);
321   EXPECT_EQ(
322       incompatible_applications_updater->GetModuleWarningDecision(module_key2),
323       IncompatibleApplicationsUpdater::ModuleWarningDecision::kIncompatible);
324 }
325 
326 // This is meant to test that cached incompatible applications are persisted
327 // through browser restarts, via the Local State file.
328 //
329 // Since this isn't really doable in a unit test, this test at least check that
330 // the list isn't tied to the lifetime of the IncompatibleApplicationsUpdater
331 // instance. It is assumed that the Local State file works as intended.
TEST_F(IncompatibleApplicationsUpdaterTest,PersistsThroughRestarts)332 TEST_F(IncompatibleApplicationsUpdaterTest, PersistsThroughRestarts) {
333   if (base::win::GetVersion() < base::win::Version::WIN10)
334     return;
335 
336   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
337 
338   auto incompatible_applications_updater =
339       CreateIncompatibleApplicationsUpdater();
340 
341   // Simulate the module loading into the process.
342   incompatible_applications_updater->OnNewModuleFound(
343       ModuleInfoKey(dll1_, 0, 0), CreateLoadedModuleInfoData());
344   incompatible_applications_updater->OnModuleDatabaseIdle();
345   RunLoopUntilIdle();
346 
347   EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
348 
349   // Delete the instance.
350   incompatible_applications_updater = nullptr;
351 
352   EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
353 }
354 
355 // Tests that applications that do not have a registry entry are removed.
TEST_F(IncompatibleApplicationsUpdaterTest,StaleEntriesRemoved)356 TEST_F(IncompatibleApplicationsUpdaterTest, StaleEntriesRemoved) {
357   if (base::win::GetVersion() < base::win::Version::WIN10)
358     return;
359 
360   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
361   AddIncompatibleApplication(dll2_, L"Bar", Option::NO_REGISTRY_ENTRY);
362 
363   auto incompatible_applications_updater =
364       CreateIncompatibleApplicationsUpdater();
365 
366   // Simulate the modules loading into the process.
367   incompatible_applications_updater->OnNewModuleFound(
368       ModuleInfoKey(dll1_, 0, 0), CreateLoadedModuleInfoData());
369   incompatible_applications_updater->OnNewModuleFound(
370       ModuleInfoKey(dll2_, 0, 0), CreateLoadedModuleInfoData());
371   incompatible_applications_updater->OnModuleDatabaseIdle();
372   RunLoopUntilIdle();
373 
374   EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
375   auto application_names =
376       IncompatibleApplicationsUpdater::GetCachedApplications();
377   ASSERT_EQ(1u, application_names.size());
378   EXPECT_EQ(L"Foo", application_names[0].info.name);
379 }
380 
TEST_F(IncompatibleApplicationsUpdaterTest,IgnoreNotLoadedModules)381 TEST_F(IncompatibleApplicationsUpdaterTest, IgnoreNotLoadedModules) {
382   if (base::win::GetVersion() < base::win::Version::WIN10)
383     return;
384 
385   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
386 
387   auto incompatible_applications_updater =
388       CreateIncompatibleApplicationsUpdater();
389 
390   // Simulate the module loading into the process.
391   ModuleInfoKey module_key(dll1_, 0, 0);
392   ModuleInfoData module_data;
393   module_data.inspection_result = base::make_optional<ModuleInspectionResult>();
394   incompatible_applications_updater->OnNewModuleFound(module_key, module_data);
395   incompatible_applications_updater->OnModuleDatabaseIdle();
396   RunLoopUntilIdle();
397 
398   EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
399   auto application_names =
400       IncompatibleApplicationsUpdater::GetCachedApplications();
401   ASSERT_EQ(0u, application_names.size());
402   EXPECT_EQ(
403       incompatible_applications_updater->GetModuleWarningDecision(module_key),
404       IncompatibleApplicationsUpdater::ModuleWarningDecision::kNotLoaded);
405 }
406 
407 // Tests that modules with a matching certificate subject are whitelisted.
TEST_F(IncompatibleApplicationsUpdaterTest,WhitelistMatchingCertificateSubject)408 TEST_F(IncompatibleApplicationsUpdaterTest,
409        WhitelistMatchingCertificateSubject) {
410   if (base::win::GetVersion() < base::win::Version::WIN10)
411     return;
412 
413   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
414 
415   auto incompatible_applications_updater =
416       CreateIncompatibleApplicationsUpdater();
417 
418   // Simulate the module loading into the process.
419   ModuleInfoKey module_key(dll1_, 0, 0);
420   incompatible_applications_updater->OnNewModuleFound(
421       module_key, CreateSignedLoadedModuleInfoData());
422   incompatible_applications_updater->OnModuleDatabaseIdle();
423   RunLoopUntilIdle();
424 
425   EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
426   auto application_names =
427       IncompatibleApplicationsUpdater::GetCachedApplications();
428   ASSERT_EQ(0u, application_names.size());
429   EXPECT_EQ(
430       incompatible_applications_updater->GetModuleWarningDecision(module_key),
431       IncompatibleApplicationsUpdater::ModuleWarningDecision::
432           kAllowedSameCertificate);
433 }
434 
435 // Registered modules are defined as either a shell extension or an IME.
TEST_F(IncompatibleApplicationsUpdaterTest,IgnoreRegisteredModules)436 TEST_F(IncompatibleApplicationsUpdaterTest, IgnoreRegisteredModules) {
437   if (base::win::GetVersion() < base::win::Version::WIN10)
438     return;
439 
440   AddIncompatibleApplication(dll1_, L"Shell Extension",
441                              Option::ADD_REGISTRY_ENTRY);
442   AddIncompatibleApplication(dll2_, L"Input Method Editor",
443                              Option::ADD_REGISTRY_ENTRY);
444 
445   auto incompatible_applications_updater =
446       CreateIncompatibleApplicationsUpdater();
447 
448   // Set the respective bit for registered modules.
449   ModuleInfoKey module_key1(dll1_, 0, 0);
450   auto module_data1 = CreateLoadedModuleInfoData();
451   module_data1.module_properties |= ModuleInfoData::kPropertyShellExtension;
452 
453   ModuleInfoKey module_key2(dll2_, 0, 0);
454   auto module_data2 = CreateLoadedModuleInfoData();
455   module_data2.module_properties |= ModuleInfoData::kPropertyIme;
456 
457   // Simulate the modules loading into the process.
458   incompatible_applications_updater->OnNewModuleFound(module_key1,
459                                                       module_data1);
460   incompatible_applications_updater->OnNewModuleFound(module_key2,
461                                                       module_data2);
462   incompatible_applications_updater->OnModuleDatabaseIdle();
463   RunLoopUntilIdle();
464 
465   EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
466   auto application_names =
467       IncompatibleApplicationsUpdater::GetCachedApplications();
468   ASSERT_EQ(0u, application_names.size());
469   EXPECT_EQ(
470       incompatible_applications_updater->GetModuleWarningDecision(module_key1),
471       IncompatibleApplicationsUpdater::ModuleWarningDecision::
472           kAllowedShellExtension);
473   EXPECT_EQ(
474       incompatible_applications_updater->GetModuleWarningDecision(module_key2),
475       IncompatibleApplicationsUpdater::ModuleWarningDecision::kAllowedIME);
476 }
477 
TEST_F(IncompatibleApplicationsUpdaterTest,IgnoreModulesAddedToTheBlacklist)478 TEST_F(IncompatibleApplicationsUpdaterTest, IgnoreModulesAddedToTheBlacklist) {
479   if (base::win::GetVersion() < base::win::Version::WIN10)
480     return;
481 
482   AddIncompatibleApplication(dll1_, L"Blacklisted Application",
483                              Option::ADD_REGISTRY_ENTRY);
484 
485   auto incompatible_applications_updater =
486       CreateIncompatibleApplicationsUpdater();
487 
488   // Set the respective bit for the module.
489   auto module_data = CreateLoadedModuleInfoData();
490   module_data.module_properties |= ModuleInfoData::kPropertyAddedToBlacklist;
491 
492   // Simulate the module loading into the process.
493   incompatible_applications_updater->OnNewModuleFound(
494       ModuleInfoKey(dll1_, 0, 0), module_data);
495   incompatible_applications_updater->OnModuleDatabaseIdle();
496   RunLoopUntilIdle();
497 
498   EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
499   auto application_names =
500       IncompatibleApplicationsUpdater::GetCachedApplications();
501   ASSERT_EQ(0u, application_names.size());
502 }
503 
TEST_F(IncompatibleApplicationsUpdaterTest,DisableModuleAnalysis)504 TEST_F(IncompatibleApplicationsUpdaterTest, DisableModuleAnalysis) {
505   if (base::win::GetVersion() < base::win::Version::WIN10)
506     return;
507 
508   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
509 
510   auto incompatible_applications_updater =
511       CreateIncompatibleApplicationsUpdater();
512 
513   incompatible_applications_updater->DisableModuleAnalysis();
514 
515   // Simulate the module loading into the process.
516   ModuleInfoKey module_key(dll1_, 0, 0);
517   incompatible_applications_updater->OnNewModuleFound(
518       module_key, CreateLoadedModuleInfoData());
519   incompatible_applications_updater->OnModuleDatabaseIdle();
520   RunLoopUntilIdle();
521 
522   // The module does not cause a warning.
523   EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
524   EXPECT_TRUE(IncompatibleApplicationsUpdater::GetCachedApplications().empty());
525   EXPECT_EQ(
526       incompatible_applications_updater->GetModuleWarningDecision(module_key),
527       IncompatibleApplicationsUpdater::ModuleWarningDecision::kNotAnalyzed);
528 }
529