blob: 4fc0a2c44e9371456ed7bb4d090432c234aeeade [file] [log] [blame]
Patrick Monettee6573792017-07-13 23:32:171// Copyright 2017 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/conflicts/enumerate_shell_extensions_win.h"
6
7#include <utility>
8
9#include "base/files/file_path.h"
10#include "base/memory/ref_counted.h"
11#include "base/metrics/histogram_functions.h"
12#include "base/sequenced_task_runner.h"
13#include "base/strings/string16.h"
14#include "base/strings/stringprintf.h"
15#include "base/task_scheduler/post_task.h"
16#include "base/task_scheduler/task_traits.h"
17#include "base/threading/sequenced_task_runner_handle.h"
18#include "base/threading/thread_restrictions.h"
19#include "base/win/registry.h"
20#include "chrome/browser/conflicts/module_info_util_win.h"
21
22namespace {
23
24void ReadShellExtensions(
25 HKEY parent,
Patrick Monette778d2ce2017-07-14 18:25:4126 const base::RepeatingCallback<void(const base::FilePath&)>& callback,
Patrick Monettee6573792017-07-13 23:32:1727 int* nb_shell_extensions) {
28 for (base::win::RegistryValueIterator iter(parent,
29 kShellExtensionRegistryKey);
30 iter.Valid(); ++iter) {
31 base::string16 key =
32 base::StringPrintf(kClassIdRegistryKeyFormat, iter.Name());
33
34 base::win::RegKey clsid;
35 if (clsid.Open(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ) != ERROR_SUCCESS)
36 continue;
37
38 base::string16 dll;
39 if (clsid.ReadValue(L"", &dll) != ERROR_SUCCESS)
40 continue;
41
42 nb_shell_extensions++;
43 callback.Run(base::FilePath(dll));
44 }
45}
46
47void OnShellExtensionPathEnumerated(
48 scoped_refptr<base::SequencedTaskRunner> task_runner,
49 OnShellExtensionEnumeratedCallback on_shell_extension_enumerated,
50 const base::FilePath& path) {
51 uint32_t size_of_image = 0;
52 uint32_t time_date_stamp = 0;
53 if (!GetModuleImageSizeAndTimeDateStamp(path, &size_of_image,
54 &time_date_stamp)) {
55 return;
56 }
57
58 task_runner->PostTask(
59 FROM_HERE, base::BindRepeating(std::move(on_shell_extension_enumerated),
60 path, size_of_image, time_date_stamp));
61}
62
63void EnumerateShellExtensionsOnBlockingSequence(
64 scoped_refptr<base::SequencedTaskRunner> task_runner,
Patrick Monette778d2ce2017-07-14 18:25:4165 OnShellExtensionEnumeratedCallback on_shell_extension_enumerated,
66 base::OnceClosure on_enumeration_finished) {
67 EnumerateShellExtensionPaths(
68 base::BindRepeating(&OnShellExtensionPathEnumerated, task_runner,
69 std::move(on_shell_extension_enumerated)));
70
71 task_runner->PostTask(FROM_HERE, std::move(on_enumeration_finished));
Patrick Monettee6573792017-07-13 23:32:1772}
73
74} // namespace
75
76const wchar_t kShellExtensionRegistryKey[] =
77 L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
78
79void EnumerateShellExtensionPaths(
Patrick Monette778d2ce2017-07-14 18:25:4180 const base::RepeatingCallback<void(const base::FilePath&)>& callback) {
Francois Doray66bdfd82017-10-20 13:50:3781 base::AssertBlockingAllowed();
Patrick Monettee6573792017-07-13 23:32:1782
83 int nb_shell_extensions = 0;
84 ReadShellExtensions(HKEY_LOCAL_MACHINE, callback, &nb_shell_extensions);
85 ReadShellExtensions(HKEY_CURRENT_USER, callback, &nb_shell_extensions);
86
87 base::UmaHistogramCounts100("ThirdPartyModules.ShellExtensionsCount",
88 nb_shell_extensions);
89}
90
91void EnumerateShellExtensions(
Patrick Monette778d2ce2017-07-14 18:25:4192 OnShellExtensionEnumeratedCallback on_shell_extension_enumerated,
93 base::OnceClosure on_enumeration_finished) {
Patrick Monettee6573792017-07-13 23:32:1794 base::PostTaskWithTraits(
95 FROM_HERE,
96 {base::MayBlock(), base::TaskPriority::BACKGROUND,
97 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
98 base::BindOnce(&EnumerateShellExtensionsOnBlockingSequence,
99 base::SequencedTaskRunnerHandle::Get(),
Patrick Monette778d2ce2017-07-14 18:25:41100 std::move(on_shell_extension_enumerated),
101 std::move(on_enumeration_finished)));
Patrick Monettee6573792017-07-13 23:32:17102}