Update code documentation for enum in EWK headers
[platform/framework/web/chromium-efl.git] / chrome / notification_helper / notification_helper_process_unittest.cc
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // This file tests launching notification_helper.exe by the OS via the registry.
6 //
7 // An advanced version of this test is
8 // chrome/browser/notifications/win/notification_helper_launches_chrome_unittest.cc,
9 // which additionally tests if chrome.exe can be successfully launched by
10 // notification_helper.exe via the NotificationActivator::Activate function.
11 //
12 // Different from this test being compiled into
13 // notification_helper_unittests.exe, the advanced test is compiled into
14 // unit_tests.exe. This is because the advanced test requires data dependency on
15 // chrome.exe which unit_tests.exe already has, and it's undesired to make
16 // notification_helper_unittests.exe have data dependency on chrome.exe.
17
18 #include <memory>
19 #include <string>
20
21 #include <wrl/client.h>
22
23 #include "base/base_paths.h"
24 #include "base/files/file_path.h"
25 #include "base/memory/ptr_util.h"
26 #include "base/path_service.h"
27 #include "base/process/process.h"
28 #include "base/process/process_iterator.h"
29 #include "base/test/test_timeouts.h"
30 #include "base/win/scoped_com_initializer.h"
31 #include "base/win/windows_types.h"
32 #include "chrome/install_static/install_util.h"
33 #include "chrome/installer/setup/install_worker.h"
34 #include "chrome/installer/util/install_util.h"
35 #include "chrome/installer/util/util_constants.h"
36 #include "chrome/installer/util/work_item.h"
37 #include "chrome/installer/util/work_item_list.h"
38 #include "testing/gtest/include/gtest/gtest.h"
39
40 namespace {
41
42 // Returns the process with name |name| if it is found.
43 base::Process FindProcess(const std::wstring& name) {
44   unsigned int pid;
45   {
46     base::NamedProcessIterator iter(name, nullptr);
47     const auto* entry = iter.NextProcessEntry();
48     if (!entry)
49       return base::Process();
50     pid = entry->pid();
51   }
52
53   auto process = base::Process::Open(pid);
54   if (!process.IsValid())
55     return process;
56
57   // Since the process could go away suddenly before we open a handle to it,
58   // it's possible that a different process was just opened and assigned the
59   // same PID due to aggressive PID reuse. Now that a handle is held to *some*
60   // process, take another run through the snapshot to see if the process with
61   // this PID has the right exe name.
62   base::NamedProcessIterator iter(name, nullptr);
63   while (const auto* entry = iter.NextProcessEntry()) {
64     if (entry->pid() == pid)
65       return process;  // PID was not reused since the PID's match.
66   }
67   return base::Process();  // The PID was reused.
68 }
69
70 }  // namespace
71
72 class NotificationHelperTest : public testing::Test {
73  public:
74   NotificationHelperTest(const NotificationHelperTest&) = delete;
75   NotificationHelperTest& operator=(const NotificationHelperTest&) = delete;
76
77  protected:
78   NotificationHelperTest() : root_(HKEY_CURRENT_USER) {}
79
80   void SetUp() override {
81     ASSERT_NO_FATAL_FAILURE(RegisterServer());
82   }
83
84   void TearDown() override {
85     ASSERT_NO_FATAL_FAILURE(UnregisterServer());
86   }
87
88  private:
89   // Registers notification_helper.exe as the server.
90   void RegisterServer() {
91     ASSERT_TRUE(scoped_com_initializer_.Succeeded());
92
93     // Notification_helper.exe is in the build output directory next to this
94     // test executable, as the test build target has a data_deps dependency on
95     // it.
96     base::FilePath dir_exe;
97     ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &dir_exe));
98     base::FilePath notification_helper_path =
99         dir_exe.Append(installer::kNotificationHelperExe);
100
101     work_item_list_ =
102         base::WrapUnique<WorkItemList>(WorkItem::CreateWorkItemList());
103
104     installer::AddNativeNotificationWorkItems(root_, notification_helper_path,
105                                               work_item_list_.get());
106
107     ASSERT_TRUE(work_item_list_->Do());
108   }
109
110   // Unregisters the server by rolling back the work item list.
111   void UnregisterServer() {
112     if (work_item_list_)
113       work_item_list_->Rollback();
114   }
115
116   // Predefined handle to the registry.
117   const HKEY root_;
118
119   // A list of work items on the registry.
120   std::unique_ptr<WorkItemList> work_item_list_;
121
122   base::win::ScopedCOMInitializer scoped_com_initializer_;
123 };
124
125 TEST_F(NotificationHelperTest, NotificationHelperServerTest) {
126   // There isn't a way to directly correlate the notification_helper.exe server
127   // to this test. So we need to hunt for the server.
128
129   // Make sure there is no notification_helper process running around.
130   base::Process helper = FindProcess(installer::kNotificationHelperExe);
131   ASSERT_FALSE(helper.IsValid());
132
133   Microsoft::WRL::ComPtr<IUnknown> notification_activator;
134   ASSERT_HRESULT_SUCCEEDED(::CoCreateInstance(
135       install_static::GetToastActivatorClsid(), nullptr, CLSCTX_LOCAL_SERVER,
136       IID_PPV_ARGS(&notification_activator)));
137   ASSERT_TRUE(notification_activator);
138
139   // The server is now invoked upon the request of creating the object instance.
140   // The server module now holds a reference of the instance object, the
141   // notification_helper.exe process is alive waiting for that reference to be
142   // released.
143   helper = FindProcess(installer::kNotificationHelperExe);
144   ASSERT_TRUE(helper.IsValid());
145
146   // Release the instance object. Now that the last (and the only) instance
147   // object of the module is released, the event living in the server
148   // process is signaled, which allows the server process to exit.
149   notification_activator.Reset();
150   ASSERT_TRUE(
151       helper.WaitForExitWithTimeout(TestTimeouts::action_timeout(), nullptr));
152 }